Drogon虽然是后端的框架,但也能实现网络客户端的相关功能。虽然在类名定义上有明确的Client的字样但对于其中设计思路一直没有梳理清楚,为什么一块完整的业务要拆成两部分?终于在看了几遍之后觉得找对了方向,故做个记录。
WebSocketClientImpl是WebSocketClient的接口实现类,由于websockect整个连接过程的发起端在客户端,所以该接口中做了TCPClient连接的创建,并发起TCP连接,借助该连接做了如下处理:
建立连接之后便是数据的收发、解析和连接状态的维护,这些无论是ws的客户端和服务端都是需要的。所以我们看到了WebSockectConnectionImp中做的事情:
服务端对协议升级的请求处理上则较为简单只要创建websockectconnection准备收发数据,没有类似websocketserver的封装。所以在HttpServer中可以看到如下代码:
// if (requestParser->firstReq() &&
// 如果是websockect的连接请求,创建webconnection的数据,处理后续的ws数据
// isWebSocket(requestParser->requestImpl()))
// {
// auto wsConn =
// std::make_shared<WebSocketConnectionImpl>(conn);
当然后端对ws处理的复杂之处在于协议转发和业务处理,所重头在router和controller。
另外,由于HttpServer本身具有TCPconnect数据回调处理的能力,所以数据回调接收部分没有作为公共业务放到WebSockectConnection中,这也是WebSockectClient中有TCPClient成员,做tcp数据回调,然后将数据转发给WebSockectConnection对象原因,服务端和客户端的职责对等,共有的业务逻辑独立封装,其他的差异业务各自封装。WebSockectConnection在ws数据解析完成后回调给client或sever对象。
TCPClient和TCP的Connection也是这个思路。类似的思路库中还有很多,比如HttpRequest与HttpRequestParser,HttpResponse和HttpResponseParser,对请求端而言,复杂之处在于响应数据的解析,所以有ResponseParser,服务端的重难点在于请求的解析,所以有了RuquestParser。复杂的单端用的业务都是单拎出来封装,更容易维护。