WebSocket协议 与 IO多路复用

最近在把 Facebook Message 接入客服系统,由于与 Facebook Message 对接的收发消息都是通过调用 http 接口来实现的,如果想实现即时通讯,还需要在中间加一个 WebSocket 来转发消息。如下图:

WebSocket协议 与 IO多路复用

其中用到了 WebSocket 协议和 IO多路复用相关的知识。在这里做一个学习记录。

为什么需要 WebSocket 协议

因为 HTTP 协议有一个缺陷:通信只能先由客户端发起,然后服务器再作出响应,并不能由服务器主动向客户端推送消息。

WebSocket 协议最大的特点是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息。

WebSocket 与 socket 的之间关系

WebSocket 是一个网络通信协议,是属于网络七层模型中的应用层的协议,同样属于应用层的协议还有 HTTP 协议、FTP协议、SMTP协议等等。

socket 是操作系统提供的一套接口,利用这一套接口就可以编写程序实现进程之间的通信、网络通信等功能。

一个 WebSocket 连接是如何建立起来的

WebSocket 连接的初期是基于 HTTP 协议的,假如 WebSocket 的地址是这个:wss://www.xxx.com/websocket ,在连接 WebSocket 的初期浏览器首先会向这个地址发出一个 HTTP GET 请求,请求头信息截图如下:

WebSocket协议 与 IO多路复用

红色框标出的是比较重要的请求头:

Connection: Upgrade 告诉服务端这个连接需要升级。

Upgrade: websocket 告诉服务端需要升级到 WebSocket 协议。

Sec-WebSocket-Key: d97OXZzuRlSJV/6SrX+uUA== 是浏览器随机生成的一个字符串。

服务端接收到这个 HTTP 请求,会作出响应,响应头的截图如下:

WebSocket协议 与 IO多路复用

红色框标出的是比较重要的响应头:

HTTP/1.1 101 Switching Protocols 告诉浏览器,服务端已经成功切换了协议。

Sec-WebSocket-Accept: axMY+KY1i8F9y9zyUMPhrfuYtPw= 这个是服务端拿到请求头中的 Sec-WebSocket-Key: d97OXZzuRlSJV/6SrX+uUA==,在 d97OXZzuRlSJV/6SrX+uUA== 后面拼接一个固定的字符串 258EAFA5-E914-47DA-95CA-C5AB0DC85B11 ,对拼接后的字符串做SHA1,得到16进制表示的字符串,将每两位当作一个字节进行分隔,得到字节数组,再对这个字节数组做Base64,得到最后的结果,把最后的结果放到 Sec-WebSocket-Accept 响应头里返回。

浏览器也会使用同样的算法把请求头中的 Sec-WebSocket-Key 算出一个结果,将这个结果与服务端返回的 Sec-WebSocket-Accept 做对比。就像对暗号一样,两边的暗号相同,WebSocket 连接就会被建立起来。这个过程也叫做握手,握手成功后,就可以愉快的使用这个 WebSocket 连接来收发消息了。

操作系统提供的 socket 接口

WebSocket 的通信,其实是利用了操作系统给我们提供的一套 socket 编程接口。接下来,我把 Linux 系统中给我们提供的 socket 头文件找出来,看看里面有哪些接口提供给我们使用,以及每个接口的作用是什么。找到 socket.h 头文件在如下位置:

WebSocket协议 与 IO多路复用

打开 socket.h 文件:

WebSocket协议 与 IO多路复用

WebSocket协议 与 IO多路复用

WebSocket协议 与 IO多路复用

打开另一个目录下的 socket.h 文件:

WebSocket协议 与 IO多路复用

socket 编程的流程如下:

WebSocket协议 与 IO多路复用

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpyppg.html