Websocket(websocket自定义协议)
是基于TCP的
tcp特征:
- 我发数据对端可以接收到,对端发数据我可以收到
- 先发先收到,后发后收到
使用websocket客户端发给服务器数据,服务器回客户端返回数据流程(自定义websocket协议需要从下三个部分考虑)
1、握手 handshake
2、发送数据和接收数据
3、断开(客户端点击断开按钮)
一、握手
问:Tcp已经握手了,为什么需要websocket需要再次握手?
答:
1、握手过程
2、服务端如果根据key换算生成一个key返回给客户端进行身份验证
过程: 身份验证的key的换算过程
1、接收到的key与一个guid字符连接
问:guid是固定的且公开的,那么为什么必须要这步呢?
答:起到填充的作用,避免传的字符少的时候不方便进行哈希
2、对新的字符进行哈希
3、做完哈希后得到sha,对哈希后的值进行base64编码
4、最后得到一个字符返回给客户端(也就是Sec-WebSocket-Accept:……)
二、发送数据过程
考虑(发送长度问题、明文还是密文)
websocket头(协议)+(payload)数据
a、不出现分包和粘包情况:
只有在发送数据,每个数据包很小,每个包之间加个延迟发送,就不用考虑分包粘包
b、数据包太大肯定要考虑分包和粘包:(websocket协议来解决分包粘包)
分包和粘包解决:1、对每个数据包前后(开始和结尾)加个分隔符
2、定一个包头(包头里面有包总长度) 下面为包头组成详解
1、客户端向服务端发送数据(服务端得到的信息)
客户端:
服务端:
2、websocket协议(包头)
通过上面传输过程得知上面发送数据后,多出来的6个字节,那这个websocket的头就是6个字节(字节总数-发送数据字节数=websocket协议头)
包头的组成部分
- 标识 =>可以根据自己喜好定义一些标识
- 长度 =>这个长度有说法,不同的长度会影响这个websocket协议的字节长度(详看下图剖析)
- masking-key =>明文、暗文的key 1密文 0明文
2-2、叙述上面发送数据案例多的6个字节是什么?
1Byte=8bit 32bit=4字节
图剖析:
剖析一:
协议头是由这部分组成
剖析二:
剖析三:
由剖析二剖析可以看到红框内一共是14个字节,但是其中有两个if
剖析四:
其中包含有两个if,payload长度满足一定条件才会算上这个字节
三种情况:根据payload长度判断
所以上面发送案例中:接收到了13个字节,实际发送给的数据7个字节,多出来的6个字节就是websocket协议头的长度
如图:
综上所述:
一个websocket包最大可以传输73bits payload length=73bits
playload length三种情况
2.3 发送数据为明文还是暗文
密文:
对称加密:1、base64、对每个字节取反 (弊端:A客户端的密文在B客户端也可以被解出来)
2、异或 (好处:A客户端的密文在B客户端不可以被解出来)
用法:对每一个字节流做个异或
传递一个32bit(4字节)的value对数据进行异或 :(可以是随机的)
异或操作公式:
异或案例解释:循环异或:案例说明
(异或中的maskkey的值是在协议头中的)
发送数据公式参数剖析:
recv(fd,buffer,length,0)
fd:
buffer:
length:是buffer的长度
- 若定义char buffer[1024] ,length就是填1024
- 填长度的意义是防止包越界
0:0明文或1暗文
三、断开
websokcet为什么单独定义一个终止包?
客户端点击断开:发送的内容如下图(只发了一个协议头,内容data为空) --终止包
接收包的协议头第一个bit(FIN)为1表示断开websocket
需要两步:1、协议头中的FIN为1,发送一个终止包,表示:先把服务端关于websocket的资源清空
2、发送FIN后,第二步调用close ,表对应示四次挥手的断开
本文来自博客园,作者:じ逐梦,转载请注明原文链接:https://www.cnblogs.com/ZhuMeng-Chao/p/17114457.html