websocket握手实现

websocket握手实现第一步,需要服务器有解析HTTP协议的能力,因为websocket的握手报文是通过HTTP协议来进行数据交互的。

1、解决HTTP的数据包正确解析。

int checkHttpRequest()
{
			//查找http消息结束标记
			char* temp = strstr(_recvBuff.data(), "\r\n\r\n");
			//未找到表示消息还不完整
			if (!temp)
				return 0;
			//偏移到消息结束位置
			//4=strlen("\r\n\r\n")
			temp += 4;
			//计算http请求消息的请求行+请求头长度
			_headerLen = temp - _recvBuff.data();
			//判断请求类型是否支持
			temp = _recvBuff.data();
			if (temp[0] == 'G' &&
				temp[1] == 'E' &&
				temp[2] == 'T')
			{
				_requestType = HttpClientS::GET;
			}
			else if (
				temp[0] == 'P' &&
				temp[1] == 'O' &&
				temp[2] == 'S' &&
				temp[3] == 'T')
			{
				_requestType = HttpClientS::POST;
				//POST需要计算请求体长度
				char* p1 = strstr(_recvBuff.data(), "Content-Length: ");
				//未找到表示格式错误
				//返回错误码或者直接关闭客户端连接
				if (!p1)
					return -2;
			   //Content-Length: 1024\r\n
				//16=strlen("Content-Length: ")
				p1 += 16;
				char* p2 = strchr(p1, '\r');
				if (!p2)
					return -2;
				//计算数字长度
				int n = p2 - p1;
				//6位数 99万9999 上限100万字节, 就是1MB
				//我们目前是靠接收缓冲区一次性接收
				//所以数据上限是接收缓冲区大小减去_headerLen
				if (n > 6)
					return -2;
				char lenStr[7] = {};
				strncpy(lenStr, p1, n);
				_bodyLen = atoi(lenStr);
				//数据异常
				if(_bodyLen < 0)
					return -2;
				//消息数据超过了缓冲区可接收长度
				if (_headerLen + _bodyLen > _recvBuff.buffSize())
					return -2;
				//消息长度>已接收的数据长度,那么数据还没接收完
				if (_headerLen + _bodyLen > _recvBuff.dataLen())
					return 0;
			}
			else {
				_requestType = HttpClientS::UNKOWN;
				return -1;
			}
			return _headerLen;
	}

2、当解析完成后,将HTTP请求的 协议版本、请求方法、字段信息。装载进对应的数据结构中。

int _headerLen = 0; 
int _bodyLen = 0;
std::map<KeyString, char*> _header_map;
std::map<KeyString, char*> _args_map;
RequestType _requestType = HttpClientS::UNKOWN;
char* _method;
char* _url;
char* _url_path;
char* _url_args;
char* _httpVersion;
bool _keepalive = true;

3、拿到了客户端请求升级为websocket的报文,服务端开启握手的流程,也就是回应一个HTTP报文给客户端。

bool handshake()
{
			auto strUpgrade = this->header_getStr("Upgrade", "");
			if (0 != strcmp(strUpgrade, "websocket"))
			{
				CELLLog_Error("WebSocketClientS::handshake, not found Upgrade:websocket");
				return false;
			}

			auto cKey = this->header_getStr("Sec-WebSocket-Key", nullptr);
			if (!cKey)
			{
				CELLLog_Error("WebSocketClientS::handshake, not found Sec-WebSocket-Key");
				return false;
			}

			std::string sKey = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";

			sKey = cKey + sKey;

			unsigned char strSha1[20] = {};
			SHA1_String((const unsigned char*)sKey.c_str(), sKey.length(), strSha1);

			std::string sKeyAccept = Base64Encode(strSha1, 20);

			// 组装好握手报文回复给客户端
			char resp[256] = {};
			strcat(resp, "HTTP/1.1 101 Switching Protocols\r\n");
			strcat(resp, "Connection: Upgrade\r\n");
			strcat(resp, "Upgrade: websocket\r\n");
			strcat(resp, "Sec-WebSocket-Accept: ");
			strcat(resp, sKeyAccept.c_str());
			strcat(resp, "\r\n\r\n");

			this->SendData(resp, strlen(resp));

			return true;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值