手写WebSocket服务器-02-相关代码

手写WebSocket服务器-02-相关代码

1.基础通信

需要声明的是,这个所谓的websocket服务器,本质上仍然是一个tcp服务器,跟web服务器原理一致,只不过web服务器实现的是http协议,websocket服务器实现的是websocket协议。

关于基础通信部分的代码,我们在web服务器系列文章中已经详细做过说明,因此这里不再重复讲解。

下面我们直接讲业务部分。

2.握手数据

前一篇文章提到,正式开始websocket协议通信前, 需要先经历一个握手的过程,在这个过程中,服务器收到的数据是:

服务器应答的数据是:

服务器收到数据后,执行了如下代码:

第一段主要是做下基本的正确性判断,确保握手请求是用http的GET协议发出的。

第二段是从请求文本中提取出了如下信息:

这个信息是浏览器端生成的一个字符串,服务端需要经过一系列的处理,将其生成下面的字符串返回给浏览器端,以验证基本的通信安全性:

处理的过程是怎样的呢?

可以看到,服务器先是将客户单发来的字符串与一个固定的字符串进行拼接(这个固定的串叫GUID)。

然后调用SHA1算法,为这个新的拼接字符串生成摘要。

然后将这个摘要用base64进行编码,就最终生成了要返回给浏览器的字符串。

服务器将这个字符串打包成HTTP应答,直接发送给客户端,就完成了websocekt协议的握手过程。

后续双方就使用正常的websocket协议进行通信了。

3.正常数据

前面的例子提到,浏览器发送了一个字符串hello给服务器,服务器又回了一个hello字符串给浏览器,那么这个过程是如何实现的呢?

首先第一步,是把从网络上收到的字节流(buf,len),调用wsc_clnt_unpack函数,解析成websocket帧,解析过程如下:

这个过程基本上是按照websocket协议逐字段解析的过程,比较繁琐,这里我们不再详细探讨(下图附websocket协议结构)。

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-------+-+-------------+-------------------------------+
|F|R|R|R| opcode|M| Payload len |    Extended payload length    |
|I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
|N|V|V|V|       |S|             |   (if payload len==126/127)   |
| |1|2|3|       |K|             |                               |
+-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
|     Extended payload length continued, if payload len == 127  |
+ - - - - - - - - - - - - - - - +-------------------------------+
|                               |Masking-key, if MASK set to 1  |
+-------------------------------+-------------------------------+
| Masking-key (continued)       |          Payload Data         |
+-------------------------------- - - - - - - - - - - - - - - - +
:                     Payload Data continued ...                :
+ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
|                     Payload Data continued ...                |
+---------------------------------------------------------------+

我们只需知道,最终他会把解析结果放在这样一个结构体中就行了:

其中data是实际的有效数据(即本例中的hello),len是有效数据的长度(本例中是5),fin表示这一批数据是不是收完了。

继续看解析代码:

可以看到,这里有一个大包拼小包的过程,目的是方便我们处理。

拼接完成后,调用wsc_clnt_handle,在这里,我们就可以实现具体的业务处理逻辑。在本例中,就是我们怎样处理收到的“hello”这个字符串。

在本例中,我们没有做任何处理,只是把收到的hello字符串,打包成websocket协议后发送了出去。

协议打包的过程也比较简单:

基本上就是填个头,拷贝下有效数据。

完。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注