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();
}

Qt websocket协议的实现的更多相关文章

  1. Websocket 协议解析

    WebSocket protocol 是HTML5一种新的协议.它是实现了浏览器与服务器全双工通信(full-duplex).          现 很多网站为了实现即时通讯,所用的技术都是轮询(po ...

  2. WebSocket协议开发

    一直以来,网络在很大程度上都是围绕着HTTP的请求/响应模式而构建的.客户端加载一个网页,然后直到用户点击下一页之前,什么都不会发生.在2005年左右,Ajax开始让网络变得更加动态了.但所有的HTT ...

  3. 初识WebSocket协议

    1.什么是WebSocket协议 RFC6455文档的表述如下: The WebSocket Protocol enables two-way communication between a clie ...

  4. Websocket协议的学习、调研和实现

    本文章同时发在 cpper.info. 1. websocket是什么 Websocket是html5提出的一个协议规范,参考rfc6455. websocket约定了一个通信的规范,通过一个握手的机 ...

  5. python测试基于websocket协议的即时通讯接口

    随着html5的广泛应用,基于websocket协议的即时通讯有了越来越多的使用场景,本文使用python中的websocket-client模块来做相关的接口测试 import webclient ...

  6. Websocket协议之php实现

    前面学习了HTML5中websocket的握手协议.打开和关闭连接等基础内容,最近用php实现了与浏览器websocket的双向通信.在学习概念的时候觉得看懂了的内容,真正在实践过程中还是会遇到各种问 ...

  7. Websocket协议数据帧传输和关闭连接

    之前总结了关于Websocket协议的握手连接方式等其他细节,现在对socket连接建立后的数据帧传输和关闭细节总结. 一.数据帧格式 数据传输使用的是一系列数据帧,出于安全考虑和避免网络截获,客户端 ...

  8. Websocket协议之握手连接

    Websocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信的问题而设计的,是完全意义上的Web应用端的双向通信技术,可以取代之前使用半双工HTTP协议而模拟全双工通信,同时克服了带 ...

  9. WebSocket协议

    websocket 简介 (2013-04-09 15:39:28) 转载▼   分类: websocket 一 WebSocket是html5新增加的一种通信协议,目前流行的浏览器都支持这个协议,例 ...

随机推荐

  1. HTML5_用语义化标记重新定义博客

    HTML5文档的第一行便是文档类型声明,文档类型声明的作用有两个 一:验证器依据文档类型来判断采用何种验证规则去验证代码 二:文档类型声明能够强制IE6,IE7,IE8以“标准模式”渲染页面 1: & ...

  2. (火炬)MS SQL Server数据库案例教程

    (火炬)MS SQL Server数据库案例教程 创建数据库: CREATE DATABASE TDB //数据库名称 ON ( NAME=TDB_dat,//逻辑文件名 在创建数据库完成之后语句中引 ...

  3. SQLSERVER中按年月分组

    SQLSERVER中按年月分组 一个表有三个字段id,dt,d  分别存放id,时间,数值  id    dt    d 1 2004-08-11 12:12:00.000 9  2 2005-09- ...

  4. 基于系统的UIMenuController的使用及自定义UIMenuItem

    1.前言 在开发中 UIMenuController 用得较少,偶尔遇到了,一时竟想不起来,因此做个回顾 2.系统默认支持 UIMenuController 的UI控件 UITextField UIT ...

  5. UI1_ViewController视图切换及Appdelegate

    // // ThirdViewController.h // UI1_ViewController视图切换及Appdelegate // // Created by zhangxueming on 1 ...

  6. php面向对象的特性:OOP的封装

    字段的作用域: 1.public 公共的(类外可以访问) 2.private 私有的(只能类内访问) 3.protected 受保护的(类内和子类可以访问,类外无法访问) /*通过公共的方法来访问私有 ...

  7. css3 画x图形

    .m-act-del{ right:; top:; margin-top: -6px; position: absolute; display: inline-block; width: 20px; ...

  8. 10款经典的web前端特效的预览及源码

    1.CSS3响应式导航菜单 今天我给大家介绍一下如何使用纯CSS来实现的一个响应式导航菜单,我们使用的是HTML5+CSS3技术,当浏览器窗口变小或者使用手机浏览器访问的时候,原本横条菜单会收缩成一个 ...

  9. 8套迷人精致的CSS3 3D按钮动画

    1.纯CSS3 3D按钮 按钮酷似牛奶般剔透 CSS3按钮一般都可以设计的非常漂亮,利用投影.渐变等CSS3属性特效可以把按钮渲染的十分动感.今天分享的这款CSS3按钮外观非常特别,它看上去酷似晶莹剔 ...

  10. WebServiceException

    在用cxf做webservice的时候,在写客户端程序的时候,出现以下异常: Could not find wsdl:binding operation info for web method tes ...