一、概述
Netty SocketIO是一个开源框架Socket.IO服务器端的一个Java的实现,它基于Netty框架,可用于服务端推送消息给客户端。
说到服务端推送技术,一般会涉及WebSocket,WebSocket是HTML5最新提出的规范,虽然主流浏览器都已经支持,但仍然可能有不兼容的情况,为了兼容所有浏览器,给程序员提供一致的编程体验,SocketIO将WebSocket、AJAX和其它的通信方式全部封装成了统一的通信接口,也就是说,使用SocketIO时不用担心兼容问题,底层会自动选用最佳的通信方式。
二、功能演示
Netty SocketIo是GitHub上的一个开源项目,作者提供了一套Demo工程,可通过Gitee上的 镜像下载地址 下载。
下载后用idea打开,以下是项目结构:
可以看一个最简单的示例,通过浏览器打开客户端页面文件event-index.html:
进入页面打开开发者工具,查看NetWork并筛选WS请求(websocket):
可以看到此时页面并没有和服务端建立连接。再打开并运行server中的连接服务EventChatLauncher.java:
可以看到控制台打印的日志,已经打开了服务端9892端口。此时回到页面,可以发现客户端已经和服务端建立好了websocket连接:
在页面上随便发送一条消息,查看效果:

此时服务端返回了客户端发送的消息,并在页面解析显示。
随后结束服务端程序,可以看到页面同样有信息返回:
三、项目集成
springboot中集成,只需要引入依赖并添加配置类注入容器中即可使用。
1、引入依赖:
<dependency><groupId>com.corundumstudio.socketio</groupId><artifactId>netty-socketio</artifactId><version>1.7.7</version></dependency>
2、配置类
@Configurationpublic class NettySocketioConfig {/*** netty-socketio服务器*/@Beanpublic SocketIOServer socketIOServer() {com.corundumstudio.socketio.Configuration config = new com.corundumstudio.socketio.Configuration();config.setHostname("localhost");config.setPort(9092);SocketIOServer server = new SocketIOServer(config);return server;}/*** 用于扫描netty-socketio的注解,比如 @OnConnect、@OnEvent*/@Beanpublic SpringAnnotationScanner springAnnotationScanner() {return new SpringAnnotationScanner(socketIOServer());}}
3、消息类(可选)
@Datapublic class Message {private String msg;}
4、消息处理器
@Component@Slf4jpublic class MessageEventHandler {@Autowiredprivate SocketIOServer socketIoServer;public static ConcurrentMap<String, SocketIOClient> socketIOClientMap = new ConcurrentHashMap<>();/*** 客户端连接的时候触发** @param client*/@OnConnectpublic void onConnect(SocketIOClient client) {String mac = client.getHandshakeData().getSingleUrlParam("mac");//存储SocketIOClient,用于发送消息socketIOClientMap.put(mac, client);//回发消息client.sendEvent("message", "onConnect back");log.info("客户端:" + client.getSessionId() + "已连接,mac=" + mac);}/*** 客户端关闭连接时触发** @param client*/@OnDisconnectpublic void onDisconnect(SocketIOClient client) {log.info("客户端:" + client.getSessionId() + "断开连接");}/*** 客户端事件** @param client 客户端信息* @param request 请求信息* @param data 客户端发送数据*/@OnEvent(value = "messageevent")public void onEvent(SocketIOClient client, AckRequest request, Message data) {log.info("发来消息:" + data);//回发消息client.sendEvent("messageevent", "我是服务器都安发送的信息");//广播消息sendBroadcast();}/*** 广播消息*/public void sendBroadcast() {for (SocketIOClient client : socketIOClientMap.values()) {if (client.isChannelOpen()) {client.sendEvent("Broadcast", "当前时间", System.currentTimeMillis());}}}}
5、事件类(可选)
public interface SocketEvent {public String MsgEvent = "messageevent";}
6、前端页面(了解)
<!doctype html><html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width,initial-scale=1, maximum-scale=1, user-scalable=no"><title>websocket-java-socketio</title><script src="https://cdn.bootcss.com/socket.io/2.2.0/socket.io.js"></script></head><body><h1>Socket.io Test</h1><div><p id="status">Waiting for input</p></div><div><p id="message">hello world!</p></div><button id="connect" onClick='connect()'/>Connect</button><button id="disconnect" onClick='disconnect()'>Disconnect</button><button id="send" onClick='send()'/>Send Message</button></body><script type="text/javascript">/*** 前端js的 socket.emit("事件名","参数数据")方法,是触发后端自定义消息事件的时候使用的,* 前端js的 socket.on("事件名",匿名函数(服务器向客户端发送的数据))为监听服务器端的事件**/var socket = io.connect("http://localhost:9092?mac=2");var firstconnect = true;function connect() {if(firstconnect) {//} else {socket.socket.reconnect();}}//监听服务器连接事件socket.on('connect', function(){ status_update("Connected to Server"); });//监听服务器关闭服务事件socket.on('disconnect', function(){ status_update("Disconnected from Server"); });//监听服务器端发送消息事件socket.on('messageevent', function(data) {message(data)//console.log("服务器发送的消息是:"+data);});//断开连接function disconnect() {socket.disconnect();}function message(data) {document.getElementById('message').innerHTML = "Server says: " + data;}function status_update(txt){document.getElementById('status').innerHTML = txt;}function esc(msg){return msg.replace(/</g, '<').replace(/>/g, '>');}//点击发送消息触发function send() {console.log("点击了发送消息,开始向服务器发送消息")var msg = "我很好的,是的.";socket.emit('messageevent', {msgContent: msg});};</script></html>
参考资料: netty-socketio 概述
