WebSocket協議詳解與c c 實現

2022-02-07 11:36:17 字數 4326 閱讀 5147

websocket有公共的標準,有很多公共的庫可以使用,比如web端,各個瀏覽器都已原生的支援websocket,所以拿來即用,非常的方便。比如cocos2dx就繼承了websocket。

比如遊戲使用了websocket,那麼就可以非常容易的用web呼叫js發websocket訊息,從而模擬客戶端的操作。

websocket相對於http是長連線的,這樣就可以實現實時的推送訊息。

websocket既能支援文字格式也可以支援二進位制格式,這樣無論是js還是c++,都可以適當的選擇自己喜歡的資料格式。

websocket可以說完全治好了大家關於長連線使用什麼協議的糾結。再遊戲行業,伺服器一般都是使用c++專門開發的網路程式,常規的一般都是使用比較傳統的二進位制協議,現在想用websocket的人越來越多,但是可以用於伺服器端的websocket庫卻很少,要不就是庫太重量級依賴了太多不需要的模組要不就是繫結了特定的網路介面實現,github上搜了下還websocket庫很少。下面介紹一下我的通用websocket解析庫,具有如下特點。

輕量,只封裝websocket的解析,不依賴任何網路介面,拿來即用。

邏輯清晰,你可以直接看**,直接能夠理解websocket的協議。

one header file only。全部實現就在乙個標頭檔案裡,整合不能再容易了。

目前提供c++和c#的實現。別的語言我就沒空寫了,剛興趣的可以照貓畫虎來乙個。

模擬傳送websocket非常的容易,我們寫乙個很簡單的html+js就可以實現,當然你可以直接使用我的這個模擬客戶端: 比如我們輸入ip為127.0.0.1埠44000,將會受到這樣的文字協議。

關鍵引數有:

if (statuswebsocketconnection == -1)

if (dictparams.empty() == true)

}else if (strrecvdata.size() >= 2)

}else

}statuswebsocketconnection = 1;

if (strrecvdata.find("\r\n\r\n") == std::string::npos)//!header data not end

if (strrecvdata.find("upgrade: websocket") == std::string::npos)

std::vectorstrlines;

strsplit(strrecvdata, strlines, "\r\n");

for (size_t i = 0; i < strlines.size(); ++i)

else if (strparams.size() == 1 && strparams[0].find("get") != std::string::npos)

}

websocket因為要相容http,所以會發乙個常規的http的協議頭,然後進行一次握手從而建立安全連線。websocket握手的時候也就是建立連線後第乙個訊息會包含sec-websocket-key這個字段,伺服器接收到這個欄位後追加乙個固定的guid值"258eafa5-e914-47da-95ca-c5ab0dc85b11",然後做sha1加密並轉base64變成可見字元返回給客戶端。

}組裝成websocket協議頭如下:

客戶端收到伺服器的這個應答訊息後,握手完成,連線建立完成,開始資料傳輸。

與tcp的流式資料不同,與http相似,websocket使用幀的方式傳輸資料,這樣解包實際上是方便的,根據長度解析訊息包這個最清晰了。

abnf如下圖所示:

int nfin = ((cacherecvdata[0] & 0x80) == 0x80)? 1: 0;

int nopcode = cacherecvdata[0] & 0x0f;

//int nmask = ((cacherecvdata[1] & 0x80) == 0x80) ? 1 : 0; //!this must be 1

int npayload_length = cacherecvdata[1] & 0x7f;

int nplayloadlenbytenum = 1;

if (npayload_length == 126)

int nmaskingkeybytenum = 4;

std::string amasking_key;

amasking_key.assign(cacherecvdata.c_str() + 1 + nplayloadlenbytenum, nmaskingkeybytenum);

std::string apayload_data;

apayload_data.assign(cacherecvdata.c_str() + 1 + nplayloadlenbytenum + nmaskingkeybytenum, npayload_length);

int nleftsize = cacherecvdata.size() - (1 + nplayloadlenbytenum + nmaskingkeybytenum + npayload_length);

if (nleftsize > 0)

for (int i = 0; i < npayload_length; i++)

if (8 == nopcode)

else if (2 == nopcode || 1 == nopcode || 0 == nopcode || 9 == nopcode)

if (nfin == 1)

else

}else

}

收到ping就發pong,有可能ping的時候也帶著資料,所以要處理下。但是貌似chrome很長時間不會自動發ping。

伺服器收到close訊息可以回乙個訊息應答一下,也可以直接關閉連線。

整合到網路層

在自己的socket裡加乙個wsprotocol物件,在收到訊息的地方一般是handlerecv函式裡加一段wsprotocol判斷和處理的**就可以了,示例如下:

if (m_owsprotocol.handlerecv(buff, len))

m_owsprotocol.clearsendpkg();

const vector& recvpkg = m_owsprotocol.getrecvpkg();

for (size_t i = 0; i < recvpkg.size(); ++i)

m_owsprotocol.clearrecvpkg();

if (m_owsprotocol.isclose())

return 0;

}

WebSocket協議詳解

1.websocket 是什麼 websocket 是html5提出的乙個協議規範,參考rfc6455 websocket,通過乙個握手的機制,客戶端 瀏覽器 和伺服器 webserver 之間建立乙個tcp連線,從而方便c s之間的通訊。在websocket出現之前 web互動一般是基於 http...

WebSocket握手協議

connection keep alive 客戶端 啦啦啦,有沒有新資訊 request 服務端 沒有 response 客戶端 啦啦啦,有沒有新資訊 request 服務端 沒有。response 客戶端 啦啦啦,有沒有新資訊 request 服務端 你好煩啊,沒有啊。response 客戶端 啦...

WebSocket協議介紹

websocket,即web瀏覽器與web伺服器之間全雙工通訊標準,其中,websocket協議由ietf定位標準,websocket api由w3c定位標準。一旦web伺服器與客戶端之間建立起websocket協議的通訊連線,之後所有的通訊都依靠這個專用協議進行。通訊過程中互相傳送json xml...