介绍
目前公司服务器是c++ tcp的网络架构,现在想用这套做h5游戏,所以要扩展支持websocket通信。
那么什么是websocket?它和tcp有什么区别?这些随便一搜一大把,这里就不再科普达。通俗简单点讲websocket就是山寨版的tcp,它底层实现就是tcp,唯一的区别就是网络传输时websocket协议前面多了个标志它的包头信息。去掉前面这部分包头剩下的就和普通tcp一样了。
那么讲到这里,在现有tcp上怎么扩展支持websocket?其实就很简单呢!既然它和tcp协议上就只是多了个包头部分,那么我们的任务其实主要就是怎么解析这个包头信息了。
最后,还有一个需要注意的细节是websocket协议前后端建立连接前需要一次握手协议,触发时机是client发起connet连接请求时,会向server发送这条握手的协议,server收到后要回复client,这样就建立了连接了。
好~闲话少说,下面直接上实现代码…
实现
1.握手。 client第一次connet连接会发起握手协议,server在recv接收处解析,判断如果是websocket的握手协议,那么同样组装好特定格式包头回复给client,建立连接。
bool isWSHandShake(std::string &request)
{
size_t i = request.find("GET");
if(i == std::string::npos){
return false;
}
return true;
}
- 如果是,解析握手协议重新组装准备send回复给client
bool wsHandshake(std::string &request, std::string &response)
{
2.接收client协议解析
bool wsReadHeader(const unsigned char* cData, WebSocketStreamHeader* header)
{
if (cData == NULL) return false;
const unsigned char *buf = cData;
header->fin = buf[0] & 0x80;
header->masked = buf[1] & 0x80;
unsigned char stream_size = buf[1] & 0x7F;
header->opcode = buf[0] & 0x0F;
if (header->opcode == WS_FrameType::WS_CONTINUATION_FRAME) {
bool wsDecodeFrame(const WebSocketStreamHeader& header, unsigned char cbSrcData[], unsigned short wSrcLen, unsigned char cbTagData[])
{
const unsigned char *final_buf = cbSrcData;
if (wSrcLen < header.header_size + 1) {
return false;
}
char masks[4];
memcpy(masks, final_buf + header.mask_offset, 4);
memcpy(cbTagData, final_buf + header.mask_offset + 4, header.payload_size);
for (INT_PTR i = 0; i < header.payload_size; ++i){
cbTagData[i] = (cbTagData[i] ^ masks[i % 4]);
}
3.组装server发给client协议
bool wsEncodeFrame(std::string inMessage, std::string &outFrame, enum WS_FrameType frameType)
{
const uint32_t messageLength = inMessage.size();
if (messageLength > 32767)
{
至此,tcp上扩展websocket所需要处理的3大块就都完成了,即握手、接收解析、发送组装。
|
请发表评论