MQTT协议笔记之mqtt.io项目Websocket协议支持
前言
MQTT协议专注于网络、资源受限环境,建立之初不曾考虑WEB环境,倒也正常。虽然如此,但不代表它不适合HTML5环境。
HTML5 Websocket是建立在TCP基础上的双通道通信,和TCP通信方式很类似,适用于WEB浏览器环境。虽然MQTT基因层面选择了TCP作为通信通道,但我们添加个编解码方式,MQTT Over Websocket也可以的。
这样做的好处,MQTT的使用范畴被扩展到HTML5、桌面端浏览器、移动端WebApp、Hybrid等,多了一些想像空间。这样看来,无论是移动端,还是WEB端,MQTT都会有自己的使用空间。
浏览器支持
话说,现代化浏览器都已经支持Websocket,这里有一个所有浏览器支持列表:
![]()
更详细列表,请直接访问:http://caniuse.com/websockets
毫无疑问,火狐和谷歌浏览器带动了现代浏览器的发展,对HTML5标准的支持也是如此。支持Websocket的浏览器单纯从上面数字来讲,73.88%的支持率。但实际上还得参考浏览器市场占有率:
![]()
上图数据,来源于: 2014年4月份全球主流浏览器市场份额排行榜
超过60%用户机器上浏览器的支持Websocket,数据很可观。
移动hybrid型应用会很欢迎Websocket
- 内置浏览器支持HTML5,Javascript操作Websocket连接MQTT
- 借助于原生TCP socket通道连接MQTT服务器,暴露JavaScript接口,间接使用
不支持Websocket的桌面浏览器,可以考虑Flash socket来帮忙!
针对不支持websocker的部分历史浏览器,可以考虑一下Flash socket,虽然使用Flashsocket用以模拟Websocket就很容易理解,但条件如下: - 需要单独占用一个端口专用于安全跨域访问策略 - 需要浏览器支持二进制Blob 支持二进制操作的浏览器现状:
![]()
比较一下支持Websocket和XHR2的桌面浏览器,重叠率很高,使用Flash Socket用以模拟Websocket必要性不大,在类似于IE平台上,不如直接使用Flash版本的
https://github.com/yangboz/as3MQTT/tree/master/MQTTClient_AS3
不支持Websocket浏览器怎么办
不是所有浏览器都支持Websocket,尤其是阻碍历史发展的IE6/IE7/IE8/IE9。MQTT协议为二进制协议压根和HTTP纯文本不兼容,尤其浏览器端JavaScript处理文本很合适,但二进制就显得笨手笨角,除非支持XHR2。
- 单独使用Flash MQTT Client,这这方面见解不深,实践很少,不便多说,您要是很了解,不妨告知一二。
- HTTP纯文本方式进行二进制对接
这部分后面专门会讲到。
服务器端支持
现有一些解决方案可能是后面为MQTT Broker,前面是添加一层代理。比如:例如 mod_websocket ,对应在线示范:http://test.mosquitto.org/ws.html
表面上看着很解藕的,实际上模仿的还是传统型的短连接反向代理架构:Nginx/Apache +Java/PHP/Python/Ruby。
客户端建立一条连接,服务器端需要使用到至少两个文件句柄,中间多了一层路径。优雅的解决方案,可以向socket.io看起。一套服务端程序,同时提供若干种协议供终端选择。其实,一台MQTT Broker中间件服务器,可以绑定多个端口,一个面向纯TCP的1883端口,一个面向Websocket的80/8080端口,共享基础逻辑,面向不同协议。
Websocket协议适配
服务器添加对Websocket支持,基本不用做多大改动。对比Tcp的附加到单个Channel的处理器列表:
| 1234567891011 |
public class TcpChannelInitializer extends ChannelInitializer<SocketChannel> {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(
new MqttMessageNewEncoder(),
new MqttMessageNewDecoder(),
new MqttMessageHandler());
}
}
|
Websocket对应单个Channel的处理器列表:
| 12345678910111213141516171819202122232425262728293031323334 |
import io.mqtt.handler.HttpRequestHandler;
import io.mqtt.handler.MqttMessageHandler;
import io.mqtt.handler.coder.MqttMessageWebSocketFrameDecoder;
import io.mqtt.handler.coder.MqttMessageWebSocketFrameEncoder;
import io.mqtt.handler.http.HttpJsonpTransport;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpObjectAggregator;
import io.netty.handler.codec.http.HttpServerCodec;
import io.netty.handler.codec.http.websocketx.WebSocketServerProtocolHandler;
public class WebsocketChannelInitializer extends ChannelInitializer<SocketChannel> {
private final static String websocketUri = "/websocket";
private HttpRequestHandler httpRequestHandler = new HttpRequestHandler(
websocketUri);
static {
HttpJsonpTransport httpJsonpTransport = new HttpJsonpTransport();
HttpRequestHandler.registerTransport(httpJsonpTransport);
}
@Override
public void initChannel(final SocketChannel ch) throws Exception {
ch.pipeline().addLast(
new HttpServerCodec(),
new MqttMessageWebSocketFrameEncoder(),
new HttpObjectAggregator(65536),
httpRequestHandler,
new WebSocketServerProtocolHandler(websocketUri),
new MqttMessageWebSocketFrameDecoder(),
new MqttMessageHandler());
}
}
|
为了支持Websocket协议,仅仅额外增加了:
| 1234567891011121314 |
@Sharable
public class MqttMessageWebSocketFrameEncoder extends
MessageToMessageEncoder<Message> {
@Override
protected void encode(ChannelHandlerContext ctx, Message msg,
List<Object> out) throws Exception {
if (msg == null)
return;
byte[] data = ((Message) msg).toBytes();
out.add(new BinaryWebSocketFrame(Unpooled.wrappedBuffer(data)));
}
}
|
| 1234567891011121314151617 |
public class MqttMessageWebSocketFrameDecoder extends
MessageToMessageDecoder<BinaryWebSocketFrame> {
private MqttMessageNewDecoder messageNewDecoder;
public MqttMessageWebSocketFrameDecoder() {
messageNewDecoder = new MqttMessageNewDecoder();
}
@Override
protected void decode(ChannelHandlerContext ctx,
BinaryWebSocketFrame wsFrame, List<Object> out) throws Exception {
ByteBuf buf = wsFrame.content();
this.messageNewDecoder.decode(ctx, buf, out);
}
}
|
小结
啰啰嗦嗦的讲了一大通Websocket,总之对Websocket的支持还算容易。后面有时间写写如何使用HTTP协议达到MQTT OVER HTTP的效果。
原文 http://www.blogjava.net/yongboy/archive/2014/05/26/414130.html
MQTT协议笔记之mqtt.io项目Websocket协议支持的更多相关文章
- MQTT协议笔记之mqtt.io项目TCP协议支持
前言 MQTT定义了物联网传输协议,其标准倾向于原始TCP实现.构建于TCP的上层协议堆栈,诸如HTTP等,在空间上多了一些处理路径,稍微耗费了CPU和内存,虽看似微乎其微,但对很多处理能力不足的嵌入 ...
- MQTT学习笔记——Yeelink MQTT维修 采用mqtt.js和paho-mqtt
0 前言 2014年8月yeelink推出基于MQTT协议的开关类型设备控制API.相比于基于HTTP RESTful的轮训方式,通过订阅相关主题消息,能够远程控制类应用实时性更好. 本文使用 ...
- MQTT协议笔记之mqtt.io项目HTTP协议支持
前言 MQTT协议诞生之初,就未曾考虑通过HTTP传输.这也正常,网络受限.不稳定网络不太适合HTTP(2G/3G网络大家使用WAP不也OK嘛).在网络较为充裕的桌面端而言,虽纯文本对比二进制而言没多 ...
- WebSocket协议探究(三):MQTT子协议
一 复习和目标 1 复习 Nodejs实现WebSocket服务器 Netty实现WebSocket服务器(附带了源码分析) Js api实现WebSocket客户端 注:Nodejs使用的Socke ...
- WebSocket协议探究(序章)
一 WebSocket协议基于HTTP和TCP协议 与往常一样,进入WebSocket协议学习之前,先进行WebSocket协议抓包,来一个第一印象. WebSocket能实现客户端和服务器间双向.基 ...
- WebSocket 协议
1.1 背景知识 由于历史原因,在创建一个具有双向通信机制的 web 应用程序时,需要利用到 HTTP 轮询的方式.围绕轮询产生了 “短轮询” 和 “长轮询”. 短轮询 浏览器赋予了脚本网络通信的编程 ...
- WebSocket协议入门介绍
目录 目录 WebSocket协议是什么 WebSocket是应用层协议 WebSocket与Http的区别 为什么要使用WebSocket 如何使用WebSocket 客户端API 在客户端使用We ...
- Websocket协议的学习、调研和实现
本文章同时发在 cpper.info. 1. websocket是什么 Websocket是html5提出的一个协议规范,参考rfc6455. websocket约定了一个通信的规范,通过一个握手的机 ...
- Websocket协议之握手连接
Websocket协议是为了解决web即时应用中服务器与客户端浏览器全双工通信的问题而设计的,是完全意义上的Web应用端的双向通信技术,可以取代之前使用半双工HTTP协议而模拟全双工通信,同时克服了带 ...
随机推荐
- 初看mysql源代码之mysql.cc
在mysql的源代码目录中,sql目录是mysql源代码中经常变化的目录之一,也是MySQL服务器内核最为核心和重要的目录. sql目录除了包含mysqld.cc这一MySQL main函数所在文件外 ...
- mysql插入、更新与删除
数据库增删改查都是要熟练掌握的. 这部分就来看看前面3个比较简单的部分,增,删,改. 插入数据 为表的所有字段插入数据 insert into table_name (column_list) val ...
- ftp 长传报错553 可能是选的目录不对
ftp> put /root/20180711tmp.txt /cc.txt local: /root/20180711tmp.txt remote: /cc.txt 200 PORT comm ...
- find 下参数的关系默认是and 一个参数多个选项可以用 -or
[root@ob2 mytmp]# find -type f -name "*.html" -or -name "*.txt"./02.html./aa.htm ...
- 关于Struts2的jsp页面的注释
语句就算用<!-- -->注释后,还是会在编译的时候显示在网页上,而且网页还会报错,因为注释的那些语句也会去编译,也会去检查有没有错误,所以一些注释掉的过时的变量和方法也会导致报错.500
- Hibernate 注解中CascadeType用法汇总
这两天,参加一个课程设计,同时这个项目又作为一个模块镶嵌到其他项目中,考虑如此,应与原先的架构相同,因牵扯到留言和相互@功能,故数据库之间OneToOne,OneToMany,ManyToMany之风 ...
- Blend for Visual Studio 2013
软件开发中为了使设计师和程序员“并行”工作并直接参与到程序的开发中来. 1.在网络程序开发团队中,草图设计后,设计师们可以使用HTML.CSS.JavaScript直接生成UI,程序员则在这个UI产生 ...
- Ubuntu server版上使用命令行操作VPNclient
Ubuntu server版上使用命令行操作VPNclient VPN,虚拟专用网络,这个技术还是非常有用的.近期笔者參与的项目中就使用上了VPN,大概情况是这种.有两个开发团队,在异地,代码服务器在 ...
- 【Java面试题】8 面向对象的特征有哪些方面 ?
面向对象的编程语言有封装.继承 .抽象.多态等4个主要的特征. 1封装: 封装是保证软件部件具有优良的模块性的基础,封装的目标就是要实现软件部件的“高内聚.低耦合”,防止程序相互依赖性而带来的变动影响 ...
- Windows性能监视器
前端时间在做动态目标监控,应用程序需要考虑大数据量和多用户并发的操作,系统的性能是解决方案实施性的重要度量.这里简单的记录下Windows中性能监视查看和简单分析. 一般操作系统性能主要涉及到的问题主 ...