IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> websocket的通信过程分析 -> 正文阅读

[网络协议]websocket的通信过程分析


一、websocket

解决http一连接只有一请求、服务器不能主动发请求的弊端。

二、两次握手过程

服务器收到请求后,会判断出不是http协议而是websocket协议,同时获取从websocket客户端传来的key ,然后server接收处理后返回一个value给客户端。
具体的处理过程分为以下3步
1.str = key|GUID
2.sha = SHA-1(str)
3.value = base64_encode(sha)

#define GUID		"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
int ws_handshark(struct ntyevent *ev) {

	int idx = 0;
	char sec_data[128] = {0};
	char sec_accept[128] = {0};

	do {
		char linebuf[1024] = {0};
		idx = readline(ev->buffer, idx, linebuf);

		if (strstr(linebuf, "Sec-WebSocket-Key")) {
		
			strcat(linebuf, GUID);
			SHA1(linebuf+19, strlen(linebuf+19), sec_data);
			base64_encode(sec_data, strlen(sec_data), sec_accept);		

			printf("idx: %d, line: %ld\n",idx, sizeof("Sec-WebSocket-Key: "));
			memcpy(ev->sec_accept, sec_accept, ACCEPT_KEY_LENGTH);

		}

	} while((ev->buffer[idx] != '\r' || ev->buffer[idx+1] != '\n') && idx != -1);

}

三、传输格式

握手成功后表示建立连接完成,开始数据传输,数据格式如下:
在这里插入图片描述
前面2字节头部主要关注MaskPayload len ,Mask位为1,表示该帧数据采用密文传输。那密文从哪算起呢?后面的Extended payload length是变化的。如果Payload len = 126,就占16bit ,如果Payload = 17,就占64位,如果小于126,就没有Extended payload length。
然后Mask为1,从Extended payload lenth后就是4字节的Masking-key, 为0则表示明文没有Masking-key,最后是我们的Payload Data数据。代码片如下:

struct ws_ophdr {

	unsigned char opcode:4,
				rsv3:1,
				rsv2:1,
				rsv1:1,
				fin:1;

	unsigned char pl_len:7,
	 			  mask:1;

};
int ws_tranmission(struct ntyevent *ev) {

	struct ws_ophdr *hdr = (struct ws_ophdr *)ev->buffer;

	if (hdr->pl_len < 126) {

		unsigned char *payload = NULL;
		if (hdr->mask) {
			payload = ev->buffer + 6;

			umask(payload, hdr->pl_len, ev->buffer + 2);
		} else {
			payload = ev->buffer + 2;
		}
}

四、解码实现

解密需要用到加密后的payload数据、长度、mask_key参数。


void umask(char *payload, int length, char *mask_key) {
	//payload是加密后的数据
	int i = 0;

	for (i = 0;i < length;i ++) {
		payload[i] ^= mask_key[i%4];
	}

}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-09-13 11:52:32  更:2022-09-13 11:53:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 23:00:06-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码