Delphi 的Websocket Server 控件实现(一、WebSocket 原理)(含源码)

目录

一、WebSocket 原理

1、握手handshaking)

2、数据通信

3、通讯示例

二、WebSocket 通信需要注意点说明

1、关于帧段(碎片)规则说明

2、通信示例

待续...


一、WebSocket 原理

关于控件的源码下载见《Delphi 的Websocket Server 控件实现(四、WebSocket Demo程序使用说明)

WebSocket 标准使用 UTF8编码通信,切记!

关于WebSocket 的原理,主要是RFC 6455标准,该标准的原文参见官方:RFC 6455(2011.11),如果大家不好下载,可以直接下载这个链接:WebSoket_协议(rfc6455).pdf(71页)

WebSocket 是 HTML5 开始提供的一种在单个 TCP 连接上进行全双工通讯的协议。关于WebSocket浏览器端javascript的实现使用请参见《菜鸟教程》的HTML5 WebSocket,说的非常清楚。

WebSocket 是独立的、创建在 TCP 上的协议。

Websocket 通过HTTP/1.1 协议的101状态码进行握手。

为了创建Websocket连接,需要通过浏览器发出请求,之后服务器进行回应,这个过程通常称为“握手”(handshaking)。

握手完成之后,客户端和服务器就建立了持久连接,可以进行通信,除非任何一端主动断开。在通信过程中,客户端发给服务器端的数据是需要掩码计算的,而服务器端发给客户端的不需要。

1、握手handshaking)

客户端主动发起,客户端会给服务器端发送类似如下文本数据:

GET / HTTP/1.1
Upgrade: websocket
Connection: Upgrade
Host: 127.0.0.1:3002
Origin: http://127.0.0.1:8020
Pragma: no-cache
Cache-Control: no-cache
Sec-WebSocket-Key: Zi5YEXnU4yRo6R4hg1Wsdw==
Sec-WebSocket-Version: 13
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits, x-webkit-deflate-frame
User-Agent: Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.138 Safari/537.36

      注意客户端发送的是 GET / HTTP/1.1 打头命令,必须告诉服务器端Upgrade为websocket,Connection为Upgrade,这样服务器端就知道客户端需要进行websocket通信,此时服务器端需要取得Sec-WebSocket-Key中的钥匙串Zi5YEXnU4yRo6R4hg1Wsdw==,通过和“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”连接再SHA-1签名后Base64编码返回给客户端,客户端验证通过就完成了握手流程。

Zi5YEXnU4yRo6R4hg1Wsdw==258EAFA5-E914-47DA-95CA-C5AB0DC85B11,对这个字符串进行SHA-1签名再Base64编码,注意连接两个字符串的时候中间不能有空格。结果为:hUfGucluAOxLIDaafqTtjEZFjMs=,见下面。

服务器返回给客户端的数据如下:

HTTP/1.1 101 Switching Protocols
Connection: Upgrade
Upgrade: websocket
Sec-WebSocket-Accept: hUfGucluAOxLIDaafqTtjEZFjMs=

服务器返回101结果,同时继续返回Connection和Upgrade字段,并且返回经过签名的结果:hUfGucluAOxLIDaafqTtjEZFjMs=

2、数据通信

在数据通信过程中,使用的是帧概念,帧数据有结构规范。一个完整的数据帧,可以通过几个小帧段组成,基本的帧结构如下:

FIN:1bit  表示是不是最后一个帧段,1表示是,否则表示不是。

RSV1、RSV2、RSV3:1 bit each  暂时不需要关注,默认是0,都是一位。

Opcode: 4 bits 定义实际帧数据的类型:

           0 : 表示是一个连续的Frame
           1 : 表示是一条文本消息
           2 : 表示是流消息
           3-7 : 保留
           8 : 表示一个连接关闭
           9 : 一个ping
           A : 一个pong
           B-F : 保留  

Mask:1 bit  表示数据是否需要进行反掩码接开,1表示需要,0表示不需要

Payload length:7 bits, 7+16 bits, or 7+64 bits 这个理解上需要转换下。如果此值介于0和125之间,则为消息的长度。如果是126,则以下2个字节(16位无符号整数)是长度。如果是127,则以下8个字节(64位无符号整数)是长度。

Masking-key: 0 or 4 bytes  从客户端发送到服务器端的所有数据都包含这4个字节,此时上面的Mask位设置也必须为1,服务器端需要通过这4个字节对后续数据进行反掩码计算。如果Mask位为0,则不包含这4个字节,表示数据无需进行反掩码运算,服务器端到客户端的数据都是这样的。

Payload data:实际的数据字节流。

3、通讯示例

假如客户端需要给服务器端发送4个字母:SZHN,那么服务器端实际收到的数据为:(129, 132, 91, 168, 122, 85, 8, 242, 50, 27)

转换为HEX就是($81,$84,$5B,$A8,$7A,$55,$08,$F2,$32,$1B)根据协议解释如下:

129($81) = 1 0 0 0 0 0 0 1     前面的第一个1表示的是FIN,这是最后一帧数据,最后面的4bit也是1,表示这是一个文本消息。

132($84)= 1 0 0 0 0 1 0 0     前面的1表示Mask位,这说明随后会有4个字节的Masking-key,需要进行反掩码计算,后面的000100就是4,表示的数据长度为4,因为我们发送的就是SZHN这4个字符。

91, 168,122,85  表示的是Masking-key,需要用这4个字节循环对后续的数据进行xor反掩码计算。

8,242, 50, 27 表示数据,进行反掩码后得到的数据如下:

91 xor 8 = 83 (S)   168 xor 242 = 90 (Z)  122 xor 50 = 72 (H)   85 xor 27 = 78 (N),接出来的结果正好是SZHN。

二、WebSocket 通信需要注意点说明

1、关于帧段(碎片)规则说明

对于一帧数据(Frame),可以分成几个帧段(碎片fragmentation)发送,这样的话,规则定义如下:

  • 非分段消息由带有FIN(FIN必须设置为1)的单个框架组成和0以外的操作码;
  • 分段消息由一个带有FIN位为0并输入一个非0的操作码,后跟零个或多个帧FIN位清除,操作码设置为0,终止于一个FIN位设置为1和0操作码的单帧

举例如下:对于作为三个片段发送的文本消息,第一个片段的操作码为0x1,FIN位为0;第二个片段的操作码为0x0,FIN位为0,
    第三个片段有一个0x0操作码和一个FIN位为1,说明整个数据已经准备好了。

2、通信示例

编码类型示例
1单一非掩码帧0x81 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains "Hello")
2单一掩码帧0x81 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (contains "Hello")
3帧段(碎片)非掩码帧

0x01 0x03 0x48 0x65 0x6c (contains "Hel")

0x80 0x02 0x6c 0x6f (contains "lo")

4非掩码ping请求和掩码ping返回

0x89 0x05 0x48 0x65 0x6c 0x6c 0x6f (contains a body of "Hello",内容随意)

0x8a 0x85 0x37 0xfa 0x21 0x3d 0x7f 0x9f 0x4d 0x51 0x58 (contains a body of "Hello", 必须匹配请求)

5一帧中包含256个非掩码二进制数据0x82 0x7E 0x0100 [256 bytes of binary data]
6一帧包含64K非掩码二进制数据0x82 0x7F 0x0000000000010000 [65536 bytes of binary data]

继续....

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

海纳老吴

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值