• linkedu视频
  • 平面设计
  • 电脑入门
  • 操作系统
  • 办公应用
  • 电脑硬件
  • 动画设计
  • 3D设计
  • 网页设计
  • CAD设计
  • 影音处理
  • 数据库
  • 程序设计
  • 认证考试
  • 信息管理
  • 信息安全
菜单
linkedu.com
  • 网页制作
  • 数据库
  • 程序设计
  • 操作系统
  • CMS教程
  • 游戏攻略
  • 脚本语言
  • 平面设计
  • 软件教程
  • 网络安全
  • 电脑知识
  • 服务器
  • 视频教程
  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号
您的位置:首页 > 程序设计 >JavaScript > 理解websocket协议解决消息发送问题 Could not decode a text frame as UTF-8.

理解websocket协议解决消息发送问题 Could not decode a text frame as UTF-8.

作者:man_sion的博客 字体:[增加 减小] 来源:互联网 时间:2017-08-17

man_sion的博客通过本文主要向大家介绍了websocket 协议报文 could等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com

在一个项目中采用websocket发送数据,浏览器JS代码与服务器建立了websocket连接,因为服务器的websocket 协议是自己实现的,所以在通信过程中websocket连接会断开,浏览器报错如下:Could not decode a text frame as UTF-8.

看样子是浏览器收到了数据帧,但是按照UTF-8解码出错(我猜测有可能发的数据按照UTF-8解码,会有一部分违反编码规则的数据存在),因为我发的是图像帧的纯字节数据,于是研究了一下Websocket 的协议,发现Websocket 报文协议格式如下:

 

 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 ...                |
 +---------------------------------------------------------------+


各个字段含义如下:

 

FIN 为 1 代表是最后一个包,后面没有数据包了,为0 则表示还有数据包

RSV 是保留的扩展定义位,没有扩展的情况下为0

opcode 用于表示消息类型,如果接收到未知的opcode,接收端必须关闭连接。目前定义的消息类型如下:

 

0x0表示附加数据帧
0x1表示文本数据帧
0x2表示二进制数据帧
0x3-7暂时无定义,为以后的非控制帧保留
0x8表示连接关闭
0x9表示ping
0xA表示pong
0xB-F暂时无定义,为以后的控制帧保留

MASK:1位,用于标识PayloadData是否经过掩码处理,客户端发出的数据帧需要进行掩码处理,所以此位是1。数据需要解码,而浏览器发送的数据必须没有掩码处理,如果客户端收到掩码处理的数据,必须主动断开连接。

 

PayloadData的长度:7位,7+16位,7+64位
如果其值在0-125,则是payload的真实长度。
如果值是126,则后面2个字节形成的16位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。
如果值是127,则后面8个字节形成的64位无符号整型数的值是payload的真实长度。注意,网络字节序,需要转换。
长度表示遵循一个原则,用最少的字节表示长度(我理解是尽量减少不必要的传输)。举例说,payload真实长度是124,在0-125之间,必须用前7位表示;不允许长度1是126或127,然后长度2是124,这样违反原则。

PayloadData 这个就是websocket 发送的纯数据了,不必多说啦。

 

 

回到我的问题,因为我发送的数据是图像帧的字节数据,所以应该是二进制,注意到opcode,我的程序中在包头第一个字节写入了一个数字“129”(用的github上的开源代码)。这个数字转成二进制后“10000001“赶紧改成130(10000010),这样浏览器就不会将数据按照UTF-8解码而报错了,完美解决问题,看来以后有问题还是得看协议规范的定义。

 

最后,啰嗦一下websocket的建立,其实websocket 就是解决http不能长连接的问题的,底层基于TCP/IP(因为要长连接嘛),websocket 的建立过程如下:

 

1、客户端在连接请求时候发送的内容

GET / HTTP/1.1
Connection:Upgrade//表示要升级连接
Host:127.0.0.1:8088
Origin:null
Sec-WebSocket-Extensions:x-webkit-deflate-frame//这个不太清楚
Sec-WebSocket-Key:puVOuWb7rel6z2AVZBKnfw==//websocket密钥,服务器会根据这个生成回应
Sec-WebSocket-Version:13//websocket 版本
Upgrade:websocket//升级到websocket

这个请求报文还是http报文发送滴,但是多了几个头字段

2、服务端接收请求后主要是成针对Sec-WebSocket-Key生成相应的加密key,采用的算法是sha1算法库,生成key后,和客户端握手成功,服务器端返回内容如下:

HTTP/1.1 101 Switching Protocols
Connection:Upgrade//
Server:beetle websocket server
Upgrade:WebSocket//升级
Date:Mon, 26 Nov 2012 23:42:44 GMT
Access-Control-Allow-Credentials:true
Access-Control-Allow-Headers:content-type
Sec-WebSocket-Accept:FCKgUr8c7OsDsLFeJTWrJw6WO8Q= //生成的东东


这样websocket 连接就建立成功了,至于websocket 能干什么,请自行百度。浏览器可以和服务器通过websocket 无拘无束的通信了。

分享到:QQ空间新浪微博腾讯微博微信百度贴吧QQ好友复制网址打印

您可能想查找下面的文章:

相关文章

  • 2017-05-11Node.js中.pfx后缀文件的处理方法
  • 2017-05-11javascript构造函数以及原型对象的理解
  • 2017-05-11js鼠标经过tab选项卡时实现切换延迟
  • 2017-05-11ES6学习教程之对象的扩展详解
  • 2017-05-11JavaScript省市级联下拉菜单实例
  • 2017-05-11JS对象深度克隆实例分析
  • 2017-05-11js获取隐藏元素的宽高
  • 2017-05-11angularJS 指令封装回到顶部示例详解
  • 2017-05-11jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
  • 2017-08-31JavaScript的数据类型

文章分类

  • JavaScript
  • ASP.NET
  • PHP
  • 正则表达式
  • AJAX
  • JSP
  • ASP
  • Flex
  • XML
  • 编程技巧
  • Android
  • swift
  • C#教程
  • vb
  • vb.net
  • C语言
  • Java
  • Delphi
  • 易语言
  • vc/mfc
  • 嵌入式开发
  • 游戏开发
  • ios
  • 编程问答
  • 汇编语言
  • 微信小程序
  • 数据结构
  • OpenGL
  • 架构设计
  • qt
  • 微信公众号

最近更新的内容

    • 解析jquery easyui tree异步加载子节点问题
    • angularjs中使用ng-bind-html和ng-include的实例
    • angular+ionic 的app上拉加载更新数据实现方法
    • 如何正确理解javascript的模块化
    • JavaScript实现简易的天数计算器实例【附demo源码下载】
    • 微信小程序 点击控件后选中其它反选实例详解
    • Vuejs入门教程之Vue生命周期,数据,手动挂载,指令,过滤器
    • 基于Bootstrap框架实现图片切换
    • 关于call和apply函数
    • JavaScript 网页中实现一个计算当年还剩多少时间的倒数计时程序

关于我们 - 联系我们 - 免责声明 - 网站地图

©2020-2025 All Rights Reserved. linkedu.com 版权所有