我是靠谱客的博主 醉熏小鸽子,最近开发中收集的这篇文章主要介绍C++实现WebSocket解析协议前提:WebSocket数据格式C++对websocket协议处理,觉得挺不错的,现在分享给大家,希望可以做个参考。
概述
前提:
本人最近做的项目,服务器端用的是C++写的,而与客户端交互用的是websocket,服务器端要想正常的使用数据,必须要对websocket协议进行解析。
解析握手协议见我上一章内容: C++实现websocket服务器握手协议
WebSocket数据格式
- FIN:表示这个数据是不是接收完毕,为1表示收到的数据是完整的,占1bit
- RSV1~3:用于扩展,通常都为0,各占1bit
- OPCODE:表示报文的类型,占4bit
- 0x00:标识一个中间数据包
- 0x01:标识一个text数据包
- 0x02:标识一个二进制数据包
- 0x03~07:保留
- 0x08:标识一个断开连接数据包
- 0x09:标识一个ping数据包
- 0x0A:标识一个pong数据包
- 0x0B~F:保留
- MASK:用于表示数据是否经常掩码处理,为1时,Masking-key即存在,占1bit
- Payload len:表示数据长度,即Payload Data的长度,当Payload len为0~125时,表示的值就是Payload Data的真实长度;当Payload len为126时,报文其后的2个字节形成的16bits无符号整型数的值是Payload Data的真实长度(网络字节序,需转换);当Payload len为127时,报文其后的8个字节形成的64bits无符号整型数的值是Payload Data的真实长度(网络字节序,需转换);
- Masking-key:掩码,当Mask为1时存在,占4字节32bit
- Payload Data:表示数据
C++对websocket协议处理
/**
* @brief getWSFrameData 解析websocket的协议包,不能解决粘包半包问题
* @param msg 待解析的数据
* @param msgLen 待解析的数据长度
* @param outBuf 解析完成数据
* @return
*/
int unPackingWSFrameData(char *msg,
int msgLen,
std::vector<char> &outBuf)
{
//报文长度一定大于2字节,对于小于的,做返回处理
if(msgLen < 2)
{
return -3;
}
uint8_t opcode_ = 0;
uint8_t mask_ = 0;
uint8_t masking_key_[4] = {0,0,0,0};
uint64_t payload_length_ = 0;
int pos = 0;
//Opcode
opcode_ = msg[pos] & 0x0f;
pos++;
//MASK
mask_ = (unsigned char)msg[pos] >> 7;
//Payload length
payload_length_ = msg[pos] & 0x7f;
pos++;
if(payload_length_ == 126)
{
uint16_t length = 0;
memcpy(&length, msg + pos, 2);
pos += 2;
payload_length_ = ntohs(length);
}
else if(payload_length_ == 127)
{
uint32_t length = 0;
memcpy(&length, msg + pos, 8);
pos += 8;
payload_length_ = ntohl(length);
}
//Masking-key
if(mask_ == 1)
{
for(int i = 0; i < 4; i++)
{
masking_key_[i] = msg[pos + i];
}
pos += 4;
}
//取出消息数据
if (msgLen >= pos + payload_length_ )
{
outBuf.clear();
if(mask_ != 1)
{
char* dataBegin = msg + pos;
outBuf.insert(outBuf.begin(), dataBegin, dataBegin+payload_length_);
}
else
{
for(uint i = 0; i < payload_length_; i++)
{
int j = i % 4;
outBuf.push_back(msg[pos + i] ^ masking_key_[j]);
}
}
}
else
{
//此时包长小于报文中记录的包长
return -2;
}
//断开连接类型数据包
if ((int)opcode_ == 0x8)
return -1;
return 0;
}
以上函数即实现了对收到websocket数据的解析,返回结果为:vector<char>output;
通常会在函数外面对此进行转换为char*,方便我们使用,见下:
vector<char>output;
char* out = &output[0];
当然,现在的解析还不是完美的解决方法,因为在实际的使用当中,会存在接收的包粘包,半包等等问题,而以上函数只能解决收到包正好是一个完整的包的情况;具体解决粘包半包问题,留待下次博客吧!
参考:
C++ 使用 websocket 协议
结尾:
只为记录,只为分享! 愿所写能对你有所帮助。不忘记点个赞,谢谢~
最后
以上就是醉熏小鸽子为你收集整理的C++实现WebSocket解析协议前提:WebSocket数据格式C++对websocket协议处理的全部内容,希望文章能够帮你解决C++实现WebSocket解析协议前提:WebSocket数据格式C++对websocket协议处理所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
发表评论 取消回复