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 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> 2.2.1 websocket协议与服务器实现 -> 正文阅读

[系统运维]2.2.1 websocket协议与服务器实现

一、websocket的使用场景

websocket 使用场景:扫码登录、股票、比赛实时比分
在这里插入图片描述
当 服务器主动推送数据给浏览器时 一般选择websocket来解

二、websocket握手的流程(handshake)

1.websocket 握手时 浏览器发送给服务器的请求协议

//websocket 握手时 浏览器发送给服务器的请求协议
GET / HTTP/1.1
Host: 192.168.247.132:8888
Connection: Upgrade  //区别HTTP / websocket协议
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36 Edg/106.0.1370.42
Upgrade: websocket  //区别HTTP / websocket协议
Origin: null
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Sec-WebSocket-Key: gSZyocBKTG+fB5zgNUdP+g==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

2.value计算流程

Key = Sec-WebSocket-Key: gSZyocBKTG+fB5zgNUdP+g==

GUID = 258EAFA5-E914-47DA-95CA-C5AB0DC85B11
//连接:
str= gSZyocBKTG+fB5zgNUdP+g==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

sha = SHA-1(str); // 做一次哈希

value = base64-encode(sha);

3.websocket 握手时 服务器返回给浏览器的协议

// 将value 返回回去,同时浏览器通过同样方式计算value
// 如果value相同则握手成功
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: value

三、基于reactor实现websocket

1.websocket_request

int websocket_request(struct ntyevent *ev) {

	if (ev->status_machine == WS_HANDSHARK) {
		
		ev->status_machine = WS_TRANMISSION;
		handshark(ev);

	} else if (ev->status_machine == WS_TRANMISSION) {

		transmission(ev);

	} else {
	
	}

	printf("websocket_request --> %d\n", ev->status_machine);
	
}

2. transmission

int transmission(struct ntyevent *ev) {

	//ev->buffer; ev->length

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

	printf("length: %d\n", hdr->pl_len);

	if (hdr->pl_len < 126) { //

		
		unsigned char *payload = ev->buffer + sizeof(ws_ophdr) + 4; // 6  payload length < 126
		if (hdr->mask) { // mask set 1

			umask(payload, hdr->pl_len, ev->buffer+2);
			
		}
		printf("payload : %s\n", payload);
		
	
	} else if (hdr->pl_len == 126) {

		ws_head_126 *hdr126 = ev->buffer + sizeof(ws_ophdr);

	} else {

		ws_head_127 *hdr127 = ev->buffer + sizeof(ws_ophdr);

	}

}

3.base64_encode

int base64_encode(char *in_str, int in_len, char *out_str) {    
	BIO *b64, *bio;    
	BUF_MEM *bptr = NULL;    
	size_t size = 0;    

	if (in_str == NULL || out_str == NULL)        
		return -1;    

	b64 = BIO_new(BIO_f_base64());    
	bio = BIO_new(BIO_s_mem());    
	bio = BIO_push(b64, bio);
	
	BIO_write(bio, in_str, in_len);    
	BIO_flush(bio);    

	BIO_get_mem_ptr(bio, &bptr);    
	memcpy(out_str, bptr->data, bptr->length);    
	out_str[bptr->length-1] = '\0';    
	size = bptr->length;    

	BIO_free_all(bio);    
	return size;
}

4.handshark


/*

ev->buffer :
ev->length

GET / HTTP/1.1
Host: 192.168.232.128:8888
Connection: Upgrade
Pragma: no-cache
Cache-Control: no-cache
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/95.0.4638.69 Safari/537.36
Upgrade: websocket
Origin: null
Sec-WebSocket-Version: 13
Accept-Encoding: gzip, deflate
Accept-Language: zh-TW,zh;q=0.9,en-US;q=0.8,en;q=0.7
Sec-WebSocket-Key: QWz1vB/77j8J8JcT/qtiLQ==
Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits

str = "QWz1vB/77j8J8JcT/qtiLQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11"

sha = SHA1(str);

value = base64_encode(sha);


*/
// 19 : length of "Sec-WebSocket-Key: "
#define WEBSOCK_KEY_LENGTH	19

int handshark(struct ntyevent *ev) {

	//ev->buffer , ev->length

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

	do {

		memset(linebuf, 0, 1024);
		idx = readline(ev->buffer, idx, linebuf);

		if (strstr(linebuf, "Sec-WebSocket-Key")) {

			//linebuf: Sec-WebSocket-Key: QWz1vB/77j8J8JcT/qtiLQ==
			strcat(linebuf, GUID);

			//linebuf: 
			//Sec-WebSocket-Key: QWz1vB/77j8J8JcT/qtiLQ==258EAFA5-E914-47DA-95CA-C5AB0DC85B11

			
			SHA1(linebuf + WEBSOCK_KEY_LENGTH, strlen(linebuf + WEBSOCK_KEY_LENGTH), sec_data); // openssl

			base64_encode(sec_data, strlen(sec_data), sec_accept);

			memset(ev->buffer, 0, BUFFER_LENGTH); 

			ev->length = sprintf(ev->buffer, "HTTP/1.1 101 Switching Protocols\r\n"
					"Upgrade: websocket\r\n"
					"Connection: Upgrade\r\n"
					"Sec-WebSocket-Accept: %s\r\n\r\n", sec_accept);

			printf("ws response : %s\n", ev->buffer);

			break;
			
		}

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

	return 0;
}

void umask(char *payload, int length, char *mask_key) {

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

}

5.效果展示

在这里插入图片描述
在这里插入图片描述

  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2022-10-17 13:11:56  更:2022-10-17 13:15:58 
 
开发: 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 18:50:19-

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