C++实现websocket服务器握手协议(使用Qt)
前提:筆者在開發server程序時,要求websocket與server連接
websocket的機制是在第一次連接時進行握手協議,協議通過,才可以進行正常的通信,否則websocket就會斷開連接;
下面就是websocket第一次發送的握手包:
GET / HTTP/1.1\r\n Host: 192.168.5.24:17913\r\n User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:69.0) Gecko/20100101 Firefox/69.0\r\n Accept: */*\r\n Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2\r\n Accept-Encoding: gzip, deflate\r\n Sec-WebSocket-Version: 13\r\n Origin: http://127.0.0.1:8848\r\n Sec-WebSocket-Extensions: permessage-deflate\r\n Sec-WebSocket-Key: tepG0DQZtEJ7MLbw7kbewA==\r\n Connection: keep-alive, Upgrade\r\n Pragma: no-cache\r\nCache-Control: no-cache\r\n Upgrade: websocket\r\n\r\n那需要對websocket發送來的第一個數據進行處理(判斷是否是第一個包,可以通過開頭GET來進行判斷,可能不是非常嚴謹),獲取Sec-WebSocket-Key的值(也就是上面的ikLk+bBgZDQRPTOBAzGsBg==),然后對此進行解析。
解析的方法是在key上加上固定字符串“258EAFA5-E914-47DA-95CA-C5AB0DC85B11”,再進行sha1解碼及base64編碼,然后打包發送給websocket客戶端。
返回的握手包如下:
HTTP/1.1 101 Switching Protocols\r\n Connection: upgrade\r\n Sec-WebSocket-Accept: mhW8gChbFWgUKJxpzcbPlcwJxcw=\r\n Upgrade: websocket\r\n\r\n代碼如下:
void rcvReadData() {QByteArray data_ = this->readAll();//socket接收數據if(!_firstConnect)//第一個包{_firstConnect = true;QString qstr_ = data_;//包數據轉化成QStringQString key_ = "";key_ = getKey(qstr_);if(key_ == "-1"){//自定義處理}else if(key_ == "-2"){//自定義處理}else{//處理keychar request[1024] = ""; //請求信息respondHandshake(request,key_.toStdString());QByteArray array_(request);write(array_);//發送數據給websocket客戶端}}else{//接下來包在此不做處理,需要涉及到websocket協議的解包} }/** *獲取Sec-WebSocket-Key的值,QT實現 */ QString getKey(QString qstr) {int i = qstr.indexOf("GET");if(i < 0){return "-1";}int j = qstr.indexOf("Sec-WebSocket-Key");if(j < 0){return "-2";}QString key = qstr.mid(j + 19, 24);return key; }/** *獲取Sec-WebSocket-Key的值,C++實現 */ string getKey(string str) {int i = str.find("GET");if(i < 0){return "-1";}int j = str.find("Sec-WebSocket-Key");if(j < 0){return "-2";}string key = str.substr(j + 19, 24);return key; }void respondHandshake(char *request, string clientkey) {strcat(request, "HTTP/1.1 101 Switching Protocols\r\n");strcat(request, "Connection: upgrade\r\n");strcat(request, "Sec-WebSocket-Accept: ");string server_key = clientkey;server_key += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";SHA1 sha;unsigned int message_digest[5];cout <<"server_key:"<< server_key << endl;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]);}base64 base64_;server_key = base64_.base64_encode(reinterpret_cast<const unsigned char*>(message_digest), 20);server_key += "\r\n";strcat(request, server_key.c_str());strcat(request, "Upgrade: websocket\r\n\r\n"); }至于代碼中出現的sha1以及base64,,可以在以下鏈接中找到,本文就不再復制粘貼了:
https://blog.csdn.net/weixin_34196559/article/details/83479894
以上只是對握手協議進行了實現,但是實際使用中,在握手完成后,對于websocket發送來的數據,還需要進行解析,才可以獲取數據,而且在解析時,還需要處理粘包半包等問題,留待下一篇文章進行闡述。
解析發送的數據,見我下一章:C++實現WebSocket解析協議
結尾:
只為記錄,只為分享! 愿所寫能對你有所幫助。不忘記點個贊,謝謝~
總結
以上是生活随笔為你收集整理的C++实现websocket服务器握手协议(使用Qt)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BUG修改:java.lang.NoCl
- 下一篇: 西门子plc s-7 1200驱动伺服电