c++ websocket客户端_实践C++写websocket服务端

c++ websocket客户端_实践C++写websocket服务端_第1张图片

背景

工作原因需要写一个websocket服务,之前是本地用python写的,但由于依赖微软的SDK,而微软SDK甚至还依赖VS编译环境,不适合用于实际用途。刚好现在在家办公闲着也是闲着,就打算用C++再来实现一遍。

关于websocket协议

这里网上搜到了一篇[ 文章 ](https://blog.csdn.net/fareise/article/details/52186217)说的比较详细,网上也有一些代码,但是好像都多少有一些问题,或者比较适用于linux。还是自己动手吧。

拿出之前python写的一个client端测试了一下:

client端代码如下:

import websocket,json,time,datetime
import json,random


data1 = {"topic":"webserver"}
datas = []
datas.append(data1)

def on_message(ws, message):
	print("收到消息",message)
	print(datetime.datetime.now())


def on_error(ws, error):
	print("on_error")
	print(error)


def on_close(ws):
	print("### closed ###")

def on_open(ws):
    for data in datas:
        ws.send(json.dumps(data))
	#print(datetime.datetime.now())


websocket.enableTrace(True)
ws = websocket.WebSocketApp("ws://localhost:8080/",
                            on_message=on_message,
                            on_error=on_error,
                            on_close=on_close,
						)
ws.on_open = on_open
    
ws.run_forever(ping_timeout=30)

1

--- request header ---
GET / HTTP/1.1
Upgrade: websocket
Host: localhost:8080
Origin: http://localhost:8080
Sec-WebSocket-Key: Ud5EMU+JiFzlcR5956u9mg==
Sec-WebSocket-Version: 13
Connection: upgrade


-----------------------

客户端发送的数据包含以上部分,其中最关键的是Sec-WebSocket-Key。收到这个信息后server端需要回复格式如下:

-----------------------
--- response header ---
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: fFsW08o/IB2Njx6nxmIzvXWGFc0=
-----------------------

其中Sec-WebSocket-Accept是根据Sec-WebSocket-Key计算得到。研究了一下,代码如下:

std::istringstream s(buff);
std::string request;
std::string server_key;

std::getline(s, request);
if (request[request.size() - 1] == 'r') {
	request.erase(request.end() - 1);
}
else 
{
	return;
}

std::string header;
std::string::size_type end;

while (std::getline(s, header) && header != "r") {
	if (header[header.size() - 1] != 'r') {
		continue; //end
	}
	else {
		header.erase(header.end() - 1);	//remove last char
	}

	end = header.find("Sec-WebSocket-Key: ", 0);
	if (end != std::string::npos) {
		server_key = header.substr(end + 19);
		break;
	}
}

//server_key = "dGhlIHNhbXBsZSBub25jZQ=="; //如果key是"dGhlIHNhbXBsZSBub25jZQ==",Accept将会是"s3pPLMBiTxaQ9kYGzzhZRbK+xOo="

cout << "[" << server_key << "]rn"; //需要将Sec-WebSocket-Key 和"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"链接,通过SHA-1 hash获得结果,然后返回该结果的base64编码


server_key += MAGIC_KEY;

SHA1 sha;
unsigned int message_digest[5];
sha.Reset();
sha << server_key.c_str();

sha.Result(message_digest);
for (int i = 0; i < 5; i++) {
	message_digest[i] = htonl(message_digest[i]);
}
server_key = base64_encode(reinterpret_cast(message_digest), 20);
cout << "[" << server_key << "]rn";

但是client端仍然会卡住不响应,反复测试了半天,包括查看buff中每个字节是否正确,并没有发现问题。无奈下又下载了网上一些开源代码研究协议,并没有找到问题,百思不得其解。突然在看一段代码的时候发现组包数据最后一行有2个rn,难道是这个原因?

果然!!!!

搞定了。

你可能感兴趣的:(c++,websocket客户端,linux,websocket)