Netty-SocketIO是一个开源的、基于Netty的、Java版的即时消息推送项目。通过Netty-SocketIO,我们可以轻松的实现服务端主动向客户端推送消息的场景,比如说股票价格变化、K线图、消息提醒等。它和websocket有相同的作用,只不过Netty-SocketIO可支持所有的浏览器。

GitHub项目地址为: https://github.com/mrniko/netty-socketio。

Socket.IO除了支持WebSocket通讯协议外,还支持许多种轮询(Polling)机制以及其它实时通信方式,并封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。Socket.IO实现的Polling通信机制包括Adobe Flash Socket、AJAX长轮询、AJAX multipart streaming、持久Iframe、JSONP轮询等。Socket.IO能够根据浏览器对通讯机制的支持情况自动地选择最佳的方式来实现网络实时应用。

###一、下载Netty-SocketIO

  1. socket.io-client-master
  2. netty-socketio-master
  3. netty-socketio-demo-master

从netty-socketio的git上可下载到以上三个压缩包,分别对应的是web 客户端的所需文件、netty socketio的java服务端实现、以及对应的可以应用web推送的demo。

###二、部署server的资源项目
从git上下载的socketio server压缩包中没有项目所需的jar包,我是自己新建了一个项目,本来上传到了CSDN的代码库里了,但写博客的时候怎么也打不开了,那么只能提供对应项目导航图,同时提供jar包的下载地址,需要的可动手去获得。

从http://mvnrepository.com/网站上课下载到需要的所有jar包。

然后将jar包添加到项目中。
切记jdk的版本一定要在1.7以上,我在本地环境中用的1.7,但是服务器上一直用的是1.6,部署项目的时候没有注意,导致服务端可以接收到客户端的socketio 的connect,但是客户端的response相应中却连接不通,开始的时候以为是跨域问题导致的,搜了好多帖子,但问题根本就是不是跨域引起的,jdk的版本换成1.7就ok了,因为netty的nio是基于java的1.7的。

###三、应用server
在需要应用socketio的项目上右键,为项目添加socketio项目支持(注意红色标出的)。

新建main类。

public static void main(String[] args) throws InterruptedException {Configuration config = new Configuration();config.setHostname("localhost");config.setPort(10015);SocketIOServer server = new SocketIOServer(config);server.addConnectListener(new ConnectListener() {// 添加客户端连接监听器@Overridepublic void onConnect(SocketIOClient client) {logger.info(client.getRemoteAddress() + " web客户端接入");client.sendEvent("helloPush", "hello");}});// 握手请求server.addEventListener("helloevent", HelloUid.class, new DataListener<HelloUid>() {@Overridepublic void onData(final SocketIOClient client, HelloUid data, AckRequest ackRequest) {// 握手if (data.getMessage().equals("hello")) {int userid = data.getUid();logger.info(Thread.currentThread().getName() + "web读取到的userid:" + userid);// send message back to client with ack callback// WITH dataclient.sendEvent("hellopush", new AckCallback<String>(String.class) {@Overridepublic void onSuccess(String result) {logger.info("ack from client: " + client.getSessionId() + " data: " + result);}}, sessionTime);} else {logger.info("行情接收到了不应该有的web客户端请求1111...");}}});server.start();Thread.sleep(Integer.MAX_VALUE);server.stop();}

当client通过ip和端口连接到server后,会构造一个SocketIOClient client的对象,在实际的应用中,可以将该client保存起来,通过client.sendEvent("helloPush", "hello");就可以向client端发送相应的数据了。

###四、应用client
####①、引入socket.io.js

<script type="text/javascript" src="${ctx}/components/socketio/socket.io.js"></script>

####②、创建connection的公共方法

function connectQuotation(uid, callback) {// 链接行情serversocket = io.connect('http://localhost:10015');// 如果用户在web端登陆,那么发送握手请求if (uid) {// 连接上server后socket.on('connect', function() {// 发送握手请求var jsonObject = {uid : parseInt(uid),message : "hello"};this.emit('helloevent', jsonObject);this.on('hellopush', function(data, ackServerCallback, arg1) {// base64转码的数据,可忽视YUNM.session = {sessionId : $.base64.atob(data.sessionId),time : $.base64.atob(data.time)};if (ackServerCallback) {ackServerCallback('server message was delivered to client!');}});});}// 如果web端session超时,socket断开,10分钟扫描一次int = window.setInterval(function() {// 我是通过ajax判断session超时的,你也可以通过其他方式$.ajax({type : 'POST',url : common.ctx + "/getSessionTimeout",dataType : "json",cache : false,success : function(json) {var timeout = parseInt(json.message);// session超时后,socket断开,服务端就可以监听到释放资源if (timeout == 0) {socket.disconnect();}},error : function() {socket.disconnect();// 清除window.clearInterval(int);}});}, YUNM._set.interval);callback();
}

####③、需要web推送的页面进行socketio的连接

$(function() {
connectQuotation($("#global_uid").val(), function() {socket.on("pushQuotation", function(message) {if (message.type == "dealOrder") {var msg = message.response.result;// 输出服务端消息YUNM.debug(msg);}});
});
});

###五、注意事项

  1. 关于socketio的ssl应用,一直没有弄出来,主要是java的toolkey生成的jks总是不被浏览器识别,socketio提供的例子也不能运行,在各大网站上暂时没有解决问题。可通过浏览器添加https的例外做法来规避错误,但不可取,后面还需要研究。
  2. socketio在浏览器刷新后,旧的连接断开,需要重新建立连接,这个请注意。
  3. 客户端session超时后,切记关闭socket,我是通过10分钟一次的扫描进行的session超时验证,该方法不够理想。
  4. server端,在实际应用中,需要将客户端断开的socket进行垃圾清理,注意判断方法如下:
NamespaceClient client = (NamespaceClient) socket;if (client.getBaseClient().isConnected()) {SessionManager.getSession(getSession().getSessionId());
} else {logger.warn("web发送心跳包失败,客户端连接线程[" + this.getName() + "]已断开");running = false;break;
}

整体Netty-SocketIO的Web推送还是非常易于掌握的,但是缺少api,做起来需要不停实践,另外解决问题的方法不多,希望本篇可以给你提供些许帮助。


2017年12月26日补充:

项目迁移到了另外一台阿里云服务器,于是Netty-SocketIO的server在启动的时候出现了以下错误:

java.net.BindException: Cannot assign requested address: bindat sun.nio.ch.Net.bind0(Native Method)at sun.nio.ch.Net.bind(Unknown Source)at sun.nio.ch.Net.bind(Unknown Source)at sun.nio.ch.ServerSocketChannelImpl.bind(Unknown Source)at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:127)

问题发生在server.start()处,进行javaChannel().bind(localAddress, config.getBacklog());域名和端口绑定时出现了错误:

private SocketIOServer server = null;
server = new SocketIOServer(NetConfigManager.getWebQuotationConfig());// 此处的Configuration对象的Hostname设置的是域名,Port设置为10015server.start();

最开始从日志里面找出了这样一条消息:

socketio.SocketIOServer$1: SocketIO server start failed at port: 10015!

直觉告诉我,阿里云的安全组在作怪,把10015端口禁掉了。于是我就去改安全组,把10015的入方向和出方向都放开了,但问题依然没有解决。

接下来,我只能丈二和尚摸不着头脑的去百度,他娘的结果没什么可靠的信息,都是一些乱七八糟的东西——什么端口被占用,使用netstat -ano查询端口,还有什么hosts文件要修改,等等,一系列坑爹又不负责任的答案。

折腾了接近四个半小时的时间,我™几乎要疯了,脑子一股热血升腾,恨不得把鼠标给砸了。

在气晕的状态下,我努力的控制着自己,问:“明明上一台阿里服务器的时候,这样配置,socketio就是正常的,现在怎么™就error了?”

试着让自己恢复冷静,就能想到办法。“不是端口的问题,那肯定是域名的问题!”

我试了试“localhost”,发现SocketIOServer竟然start成功了!????这说明什么问题,说明域名没有localhost的权限!但改成localhost有毛用,客户端不可能访问到服务器的localhost啊?

接着,我想到了IP地址!!!!!把域名换成公网的IP地址,竟然™的SocketIOServer start成功了!!!!

此时有两种解决方案,一是使用IP来替代域名,另外一个就是继续找域名的解决方案——一个不懂网络的程序员注定在网络安全方面吃点亏!,我™就是受害者之一。

好了,问题记录就先到这里——解决问题的最好办法就是让自己冷静下来!!!!


2018年9月11日补充:

由于项目在tomcat服务器的访问前缀由原来的http改为https,导致客户端的socketio无法正常访问到Netty-SocketIO服务器端。从昨天到今天,整整两天,一直在寻找解决方案,现在事情终于有所转机,为了更多小伙伴的需要,就把问题整理备案。

由于https下不允许使用http访问,所以Netty-SocketIO服务器端需要从http升级到https,具体的实例该怎么做呢?
demo可参照https://github.com/mrniko/netty-socketio-demo/blob/master/server/src/main/java/com/corundumstudio/socketio/demo/SslChatLauncher.java,但据我的实战情况来看,该官方实例无法在本地正常运行,也就是说,官方提供的https解决方案在本地是行不通的,但官方实例提供了一个keystore.jks,如果小伙伴们对keystore.jks不熟悉的话,可以先借用该jks。

有了jks,我们可以先将Server端升级到https,也就是ssl(非常抱歉,对https和ssl我还不是很清楚,但并不妨碍我将实例运行起来)。

Configuration config = new Configuration();
config.setPort(10015);
// 注意不要指定config.setHostname
// 具体原因不清楚,不得不再说一声抱歉,我在网络方面就是一个白痴,比如说我不懂hosts文件是干嘛的,也不懂内网和外网之间的区别,总之这一块使我非常焦虑,只好一步步组合方案进行试验,换句话说理论知识不够,只能靠不断试错来总结经验// keystore.jks的密钥
config.setKeyStorePassword("test1234");
InputStream stream = new FileInputStream(new File("/home/soft/keystore.jks"));
config.setKeyStore(stream);
// 升级为httpsserver = new SocketIOServer(config);

然后我们来看客户端

var socket =  io.connect('https://147.101.128.223:10015');
// 使用https而不再是http,然后紧接着是服务器的外网地址,不知道为什么,然后是对应的端口

现在,已经可以通过https来访问到socketio的服务器端了。

但遗憾的是:地址栏中的https竟然变成了不安全的状态!!!!!


2018年9月14日补充:

之前的补充当中说https的地址栏变成了不安全的状态,其实是jdk的域名不匹配,如果jks把项目实际的域名匹配上的话,就不再提示不安全了!
另外,socketio的client在链接的时候可以使用域名链接,而不只是ip地址,如下:

var socket = io.connect("cmower.com");

需要特别注意的是,Netty-SocketIO的服务器端在配置config的时候,不要指定hostname,切记!!!!

如果在启动Server的时候发现:

java.net.BindException: Address already in use
at sun.nio.ch.Net.bind0(Native Method)
at sun.nio.ch.Net.bind(Net.java:433)
at sun.nio.ch.Net.bind(Net.java:425)
at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:223)
at io.netty.channel.socket.nio.NioServerSocketChannel.doBind(NioServerSocketChannel.java:127)
at io.netty.channel.AbstractChannel A b s t r a c t U n s a f e . b i n d ( A b s t r a c t C h a n n e l . j a v a : 554 ) a t i o . n e t t y . c h a n n e l . D e f a u l t C h a n n e l P i p e l i n e AbstractUnsafe.bind(AbstractChannel.java:554) at io.netty.channel.DefaultChannelPipeline AbstractUnsafe.bind(AbstractChannel.java:554)atio.netty.channel.DefaultChannelPipelineHeadContext.bind(DefaultChannelPipeline.java:1258)
at io.netty.channel.AbstractChannelHandlerContext.invokeBind(AbstractChannelHandlerContext.java:511)
at io.netty.channel.AbstractChannelHandlerContext.bind(AbstractChannelHandlerContext.java:496)
at io.netty.channel.DefaultChannelPipeline.bind(DefaultChannelPipeline.java:980)
at io.netty.channel.AbstractChannel.bind(AbstractChannel.java:250)

可以查看是否有其他的进程占用了地址?

举个例子,在我的项目当中,如果我先启动了Tomcat,那么Netty-SocketIO的Server就会提示以上错误;假如我先启动Netty-SocketIO的Server,再启动Tomcat,两者就都正常!

所以,以上建议,请特别注意!!!!

最后,一定会有不少读者想要问我怎么学习 Java 的,那我干脆就把我看过的优质书籍贡献出来:

1)入门版:《Head First Java》、《Java 核心技术卷》

2)进阶版:《Java编程思想》、《Effective Java》、《Java网络编程》、《代码整洁之道》

3)大牛版:《Java并发编程》、《深入理解Java虚拟机》、《Java性能权威指南》、《重构》、《算法》

就先介绍这么多,希望对那些不知道看什么书的同学有所帮助。

对了,我介绍的这些书籍,已经顺便帮你整理好了,你可以在我的原创微信公众号『沉默王二』回复『书籍』获取哦

有收获?希望老铁们来个三连击,给更多的同学看到这篇文章

Netty-SocketIO:最好用的Java版即时消息推送相关推荐

  1. Java版WebSocket消息推送系统搭建

    Java版WebSocket消息推送系统搭建 最近在做消息推送,网上查了一些资料,开始想的是用MQ来做,后面发现用WebSocket来做的话感觉应该要简单点,话不多说,准备撸代码. 后端核心代码 /* ...

  2. 环境监控告警系统之TIM即时消息推送部署

    TIM是由腾讯发布的多平台客户端应用.TIM是轻聊的QQ,更方便办公.TIM用在QQ轻聊版的基础上加入了协同办公服务的支持,消息完全同步,支持多人在线编辑Word.Excel文档等,更加适合办公使用. ...

  3. 【Java集成小米消息推送(海外版)】

    Java集成小米消息推送(海外版) 注册登录: 小米推送运营中心 提交需要的信息,一般为包名等信息(或直接让Android开发提交) 需要的配置信息 1.App Secret 2.Package na ...

  4. JAVA集成unipush消息推送uniapp

    Springboot集成 pom文件引入相关jar包 <!-- https://mvnrepository.com/artifact/com.getui.push/restful-sdk --& ...

  5. flex blazeds java spring_flex+blazeds+java+spring后台消息推送,有界面维护

    之前写过一篇文章:flex+blazeds+java后台消息推送(简单示例)  ,现在要写的是这个的升级版,改动还是挺多的,在上面的基础上增加了spring配置,还有界面的维护.后台基本上全变了.呵呵 ...

  6. java即时消息推送

    整个例子的源码下载:http://pan.baidu.com/s/1gfFYSbp 下载服务端jar文件 Comet4J目前仅支持Tomcat6.7版本,根据您所使用的Tomcat版本下载[comet ...

  7. 环境监控告警系统之TIM即时消息推送部署(二)

    5.将Flexlive.CQP.PluginSolution\CQP\Publish下所有文件复制到酷Q Air根目录下图9,打开酷Q Air\conf\CQP.cfg文件,打开后把下面的代码复制到最 ...

  8. java dwr实现消息推送_dwr消息推送

    http协议本身就是请求-响应, 不可能反向.所谓的服务器push其实核心依然是依靠浏览器主动发起请求,有两种方式,一种是js轮询请求,一种是长连接. 长连接指发送请求后,服务器不是立即响应而是等到有 ...

  9. 使用swoole作为MQTT客户端并接收实现即时消息推送

    环境准备 首先需要安装 swoole 可以使用 pecl 进行安装 ,如 pecl install swool, 注意加上版本号 或者使用构建好的 docker 镜像,这里使用构建好的 zacksle ...

最新文章

  1. git 还原版本方法
  2. 创建XNA Shooter游戏——挑战:用引擎编写自己的游戏
  3. java 模拟登陆exe_Java简单模拟登陆和爬虫实例---博客园老牛大讲堂
  4. initramfs两种方法恢复_苹果手机备忘录删除了怎么恢复?两种方法,解决90%恢复问题...
  5. java中引导页面的,设计模式之模板模式引导篇
  6. vue 简单实用的elementUI表格封装
  7. 3399 mysql_手动安装 mysql
  8. 利用C语言中的setjmp和longjmp,来实现异常捕获和协程
  9. modern android5.1,Modern摩登印
  10. 比小米12 Pro还好?Redmi K50 Pro+屏幕细节曝光:2K高分直屏
  11. C++_类和对象_C++多态_虚析构和纯虚析构函数---C++语言工作笔记074
  12. 信号与槽是如何实现的_铺天盖地的吐槽,结果却是卖到断货?iPhone12魅力何在?...
  13. [javascript]实现登陆界面拖动窗口
  14. django创建博客
  15. LeetCode算法题-House Robber(Java实现)
  16. 仓库镜像源为清华_conda国内镜像修改(最新版)
  17. 李开复:中国创业有四大优势
  18. JQuery Validate(1)---电话号码与邮箱验证
  19. 2021-06-29 连续非空子序列
  20. 无U盘 安装纯净win7系统

热门文章

  1. vscode保存代码,浏览器自动刷新页面
  2. iOS警报:XcodeGhost已扩散至第三方框架
  3. 最新E4A影视APP带有独立后台源码+包含类库/ThinkPHP核心
  4. 简易数据库学习环境的搭建
  5. 城市选择与就业单位选择-成都体制内工作调研
  6. 《从容一生》-之-被爱和爱人
  7. 服务器主板数码管显示ff,ESP8266之旋转编码器与四位数码管模块显示圈数
  8. 国培-甘肃定西市新任职校长培训班莅临湖南省智慧教育装备展示体验中心参观学习
  9. 基于STM32单片机的RFID门禁显示系统
  10. 火车轨道铁路轨道检测识别(附带Python源码+详细解析)