上次我们利用一个
websocket client
的实现对ws协议
进行了详细的解析(websocket client & ws协议解析),作为一个深度强迫症犯者,那么websocket server
就必不可少了。
为了保证示例的简洁性,我们仅仅建立了支持单个客户端的 websocket 服务端的模型。而一般的网络编程模型,都是主进程一个事件监听连接,接收连接之后把连接对象抛给IO线程池(一般线程数量等于CPU核数),这个IO线程池每个人都有自己的epoll,来监听连接对象的可读事件,IO线程读取完数据,进行TCP粘包、半包处理,然后封装成task,最后丢给一个工作线程池来处理task,最后处理完task由一个专门的发送线程进行统一发送数据。
环境说明:
- 完整代码: websocket_server.c
- RFC6455协议
- gcc version 4.4.7 x86_64-redhat-linux
- websocket客户端 采用 Javascript 的
new WebSocket("ws://127.0.0.1:2346/")
系列方法
websocket server 功能流程
相比 客户端而言,服务端的流程就相对比较简单了,对比之前的一篇 websocket client & ws协议解析,我们主要对以下模块进行说明(有网络编程功底的同学可以先将例子clone下来查看,简单例子,见谅!^-^)
TCP协议族 client vs server 核心步骤和流程
服务端生成握手信息的header
解密客户端发送的数据信息
服务端生成数据帧
TCP协议族 client vs server 核心步骤和流程
服务端生成握手信息的header
服务端生成握手 header的步骤基本就是之前 client 生成验证 header的逆向思维(握手)。
状态码101
代表协议升级成功后的状态码Connection
和Upgrade
内容代表协议成功升级为wsSec-WebSocket-Version
和Server
内容代表 ws协议版本 以及 服务端服务软件信息Sec-WebSocket-Accept
重点在此,证明服务端接受了客户端的请求,然后客户端对accept值进行验证,任何 为空或者不符合验证规则的都视为服务器拒绝了请求。服务端生成 Sec-WebSocket-Accept 规则
:服务端将客户端传递的key进行去除首尾空白,然后和一段固定的GUID(258EAFA5-E914-47DA-95CA-C5AB0DC85B11)进行连接,连接后的结果使用 SHA-1(160数位)进行哈希操作,对哈希后的字符串进行base64编码,即为 Accept 内容。客户端验证规则
仿上述规则对 Sec-WebSocket-Key 进行加密,跟服务端返回 Sec-WebSocket-Accept 值进行对比即可。
上述只是基础的 header 字段,当然还会根据具体需求添加一些 cookie 或者 其他衍生字段。
生成握手信息的实现代码片段如下(请着重注意代码注释,注意事项过程
)(代码中使用的函数均会存在于完整代码中
)
解密客户端发送的数据信息
解包也属于 client 加密包的逆向思维(“数据帧”)。
解密客户端发送的数据信息 实现代码片段如下(请着重注意代码注释,注意事项过程
)(代码中使用的函数均会存在于完整代码中
)
服务端生成数据帧
打包过程与 client 基本类似,区别在于 通常client发server的数据都要 isMask(掩码) 处理, 反之server到client却不用(“数据帧”)。
服务端生成数据帧 实现代码片段如下(请着重注意代码注释,注意事项过程
)(代码中使用的函数均会存在于完整代码中
)
本文作者: wettper
本文链接: http://www.web-lovers.com/c-websocket-server.html
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 3.0 许可协议。转载请注明出处!