Qt websocket協議的實現

 
handshake(握手)
client請求:
     GET /chat HTTP/1.1
        Host: server.example.com
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ==
        Sec-WebSocket-Version: 13
server回覆:
     HTTP/1.1 101 Switching Protocols
        Upgrade: websocket
        Connection: Upgrade
        Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=

"dGhlIHNhbXBsZSBub25jZQ=="(Sec-WebSocket-Key)+"258EAFA5-E914-47DA-95CA-C5AB0DC85B11"(因定GUID)
先SHA-1哈希,再用base64編碼,獲得"s3pPLMBiTxaQ9kYGzzhZRbK+xOo="

Framing Protocol(數據幀協議)
      0                   1                   2                   3
      0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
     +-+-+-+-+-------+-+-------------+-------------------------------+
     |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
     |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
     |N|V|V|V|       |S|             |   (if payload len==126/127)   |
     | |1|2|3|       |K|             |                               |
     +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
     |     Extended payload length continued, if payload len == 127  |
     + - - - - - - - - - - - - - - - +-------------------------------+
     |                               |Masking-key, if MASK set to 1  |
     +-------------------------------+-------------------------------+
     | Masking-key (continued)       |          Payload Data         |
     +-------------------------------- - - - - - - - - - - - - - - - +
     :                     Payload Data continued ...                :
     + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
     |                     Payload Data continued ...                |
     +---------------------------------------------------------------+
opcode:
     0x1 text frame
     0x2 binary frame
     0x8 connection close
Mask:是否有掩碼(client to server必須, server to client可選)
Payload length:負載長度
     <=125 直接7位表示長度
     126,表示長充大於125並小於0xFFFF,長度放在2Byte
     127,長度放在後8Byte
Masking-key:若是有Mask,4Byte
Payload Data:若是有Mask,須要和Making-key作異或來還原數據
 
附WebSocket Protocol
http://datatracker.ietf.org/doc/rfc6455/?include_text=1
 
 
代碼 QByteArray handShake(QString secWebSocketKey) {     Q_ASSERT(!secWebSocketKey.isEmpty());     secWebSocketKey += "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";     QString s=  QCryptographicHash::hash(secWebSocketKey.toAscii(),                                          QCryptographicHash::Sha1).toBase64();     QString respone = QString("HTTP/1.1 101 Switching Protocols\r\n"                               "Upgrade: websocket\r\n"                               "Connection: Upgrade\r\n"                               "Access-Control-Allow-Credentials:true\r\n"                               "Access-Control-Allow-Headers:content-type\r\n"                               "Sec-WebSocket-Accept: %1\r\n"                               "\r\n").arg(s);     return respone.toAscii(); }      void unmask (int pos, int len, unsigned char *buf) {     int i = pos;                //The position of payload data     int n = pos - 4;            //The position of masking-key     for (; i<len; i++,n++)     {         if (n == pos) n = pos - 4;  //back to the first masking-key         buf[i] ^= buf[n];       //unmask: payload data XOR masking-key     } } QByteArray parserData(QByteArray input) {     unsigned char *buf=(unsigned char *)input.data();     QByteArray out;     int len = input.length();     if (buf[0] == 0x88)     {         qDebug()<<"Received a Close frame";         out = "close";         return out;     }     buf[1] &= 0x7F;     int payloadBegin = 0;     if (buf[1] < 126)     {         payloadBegin = 6;     }     else if (buf[1] == 126)     {         payloadBegin = 8; //6+2     }     else if (buf[1] == 127)     {         payloadBegin = 14;//6+8     }     unmask(payloadBegin, len, buf);        out = QByteArray::fromRawData((const char *)(input.data()+payloadBegin), input.size()-payloadBegin);     return out; } void writeData(QTcpSocket *socket, const QByteArray &data) {     QByteArray head(2, 0);     if (data.length()<=125)     {         quint8 len = data.length();         head[1] = len;     }     else if (data.length()<=0xffff)     {         head[1] = 126;         quint16 len = data.length();         head.resize(4);         for (int i=3; i>1; i--)         {             head[i] = (byte)(len & 0xff);             len = len >> 8;         }     }     else{         head[1] = 127;         quint64 len = data.length();         head.resize(10);         for (int i=9; i>1; i--)         {             head[i] = (byte)(len & 0xff);             len = len >> 8;         }     }     socket->write(head);     socket->write(data);     socket->flush(); }
相關文章
相關標籤/搜索