netty-socketio是基于netty的socket.io服务实现,可以无缝对接前端使用的socketio-client.js。
相对于javaee的原生websocket支持(@serverEndpoint)和spring-boot的MessageBroker(@messageMapping),netty-socketio绝对是最好用的websocket后台实现。因为netty-socketio完整的实现了socket.io提供的监听前台事件、向指定客户端发送事件、将指定客户端加入指定房间、向指定房间广播事件、客户端从指定房间退出等操作。
msg实体
package com.song.netty;import java.io.Serializable;public class Msg implements Serializable{ ???private static final long serialVersionUID = -6519304261259719883L; ???private String userId; ???private String userName; ???private String receiveUserId; ???private String content; ???public String getUserId() { ???????return userId; ???} ???public void setUserId(String userId) { ???????this.userId = userId; ???} ???public String getUserName() { ???????return userName; ???} ???public void setUserName(String userName) { ???????this.userName = userName; ???} ???public String getReceiveUserId() { ???????return receiveUserId; ???} ???public void setReceiveUserId(String receiveUserId) { ???????this.receiveUserId = receiveUserId; ???} ???public String getContent() { ???????return content; ???} ???public void setContent(String content) { ???????this.content = content; ???} ???public Msg(String userId, String userName, String receiveUserId, String content) { ???????super(); ???????this.userId = userId; ???????this.userName = userName; ???????this.receiveUserId = receiveUserId; ???????this.content = content; ???} ???public Msg() { ???????super(); ???}}
聊天室通讯服务端可与多个客户端通讯
测试方法,在不同浏览器各打开一个聊天室页面,发送消息,全部都会接收到
监听聊天室通讯事件
package com.song.netty;import com.corundumstudio.socketio.AckRequest;import com.corundumstudio.socketio.SocketIOClient;import com.corundumstudio.socketio.SocketIOServer;import com.corundumstudio.socketio.listener.DataListener;public class OneToManyChartListener implements DataListener<Msg>{ ???SocketIOServer server; ???public void setServer(SocketIOServer server) { ???????this.server = server; ???} ???public void onData(SocketIOClient socketIoClient, Msg msg, AckRequest askSender) throws Exception { ???????System.out.println("一对多"+socketIoClient.getSessionId()); ???????// chatevent为 事件的名称, data为发送的内容 ???????this.server.getBroadcastOperations().sendEvent("chatMany", msg); ???}}
点对点通讯客户端只与服务端通讯
测试方法,在不同浏览器各打开一个聊天室页面,发送消息,只有发送消息的那个客服端才能接收到消息
监听点对点通讯事件
package com.song.netty;import com.corundumstudio.socketio.AckRequest;import com.corundumstudio.socketio.SocketIOClient;import com.corundumstudio.socketio.SocketIOServer;import com.corundumstudio.socketio.listener.DataListener;public class OneToOneChartListener implements DataListener<Msg>{ ???SocketIOServer server; ???public void setServer(SocketIOServer server) { ???????this.server = server; ???} ???public void onData(SocketIOClient socketIoClient, Msg msg, AckRequest askSender) throws Exception { ???????System.out.println("一对一"+socketIoClient.getSessionId()); ???????// chatevent为 事件的名称, data为发送的内容 ???????this.server.getClient(socketIoClient.getSessionId()).sendEvent("chatOne", msg); ???}}
客户端使用socket.io,首先启动server,推送消息时服务端获取客户端,向客户端发送消息。客户端接收消息后刷新页面数据。
package com.song.netty;import com.corundumstudio.socketio.Configuration;import com.corundumstudio.socketio.SocketIOServer;public class MsgServer { ???public static void main(String[] args) throws InterruptedException { ???????Configuration config = new Configuration(); ???????config.setHostname("localhost"); ???????config.setPort(8888); ???????SocketIOServer server = new SocketIOServer(config); ???????OneToOneChartListener listner = new OneToOneChartListener(); ???????listner.setServer(server); ???????OneToManyChartListener listnerMany = new OneToManyChartListener(); ???????listnerMany.setServer(server); ???????// chatOne,chatMany为事件名称 ???????server.addEventListener("chatOne", Msg.class, listner); ???????server.addEventListener("chatMany", Msg.class, listnerMany); ???????//启动服务 ???????server.start(); ???????Thread.sleep(Integer.MAX_VALUE); ???????server.stop(); ???}}
特别注意netty的版本,版本过低会导致使用socket.io通讯时跨域
<dependency> ???<groupId>com.corundumstudio.socketio</groupId> ???<artifactId>netty-socketio</artifactId> ???<version>1.7.14</version></dependency>
跨域错误如下
XMLHttpRequest cannot load http://myserver/socket.io/1/?t=1400445162388. No ‘Access-Control-Allow-Origin‘ header is present on the requested resource. Origin ‘myclient.com‘ is therefore not allowed access.
前台测试页面代码一对一
<!DOCTYPE html><html><head><meta charset="GB2312"><title>小张唠嗑</title><base><script src="jquery-1.9.1.js" type="text/javascript"></script><script type="text/javascript" src="socket.io.js"></script><script src="ckeditor/ckeditor.js"></script><style>body { ???padding: 20px;}#console { ???height: 450px; ???overflow: auto;}.username-msg { ???color: orange;}.connect-msg { ???color: green;}.disconnect-msg { ???color: red;}.send-msg { ???color: #888}</style></head><body> ???<h1>老宋陪您唠嗑</h1> ???<!-- <br /> --> ???<div id="console" class="well"></div> ???<form class="well form-inline" onsubmit="return false;"> ???????<input id="name" ?class="input-xlarge" type="hidden" placeholder="用户名称. . . " /> ???????<!-- <input id="msg" class="input-xlarge" type="text" placeholder="发送内容. . . " /> --> ???????<textarea id="msg" rows="10" cols="50" placeholder="发送内容. . . "></textarea> ???????<button type="button" onClick="sendMessage()" class="btn">发送</button> ???????<button type="button" onClick="sendDisconnect()" class="btn">下线</button> ???????<button type="button" onClick="reloadThis()" class="btn">重连</button> ???</form></body><script type="text/javascript">var editor = CKEDITOR.replace( ‘msg‘ );editor.on("instanceReady",function(){ ???/* this.document.onkeydown=function(event){ ????????alert(0); ????????var e = event || window.event || arguments.callee.caller.arguments[0]; ????????if(event.ctrlKey&&event.keyCode==13){ // enter 键 ????????????//要做的事情 ????????????paraent.sendMessage(); ????????} ???}; ?*/ ???this.document.on("keydown",function(){ ???????//console.log(window.frames[0]); ???????var event = window.frames[0].event; ?????????if(event.ctrlKey&&event.keyCode==13){ // enter 键 ????????????//要做的事情 ???????????sendMessage(); ????????} ????});});var socket;connect();//var socket = io.connect(‘http://192.168.0.207:9092‘);function connect(){ ???socket = io.connect(‘ws://127.0.0.1:9092‘); ???$("#name").val("你的小宝贝儿"+parseInt(Math.random()*100+1, 10)); ???socket.on(‘connect‘,function() { ???????serverOutput(‘<span class="connect-msg">欢迎进入小张唠嗑聊天室!</span>‘); ???????//serverOutput(‘<span class="disconnect-msg">‘+$("#name").val()+‘已上线! </span>‘); ???????socket.emit(‘chatOne‘, { ???????????userId:1, ???????????userName : $("#name").val(), ???????????receiveUserId:2, ???????????content : "已上线!" ???????}); ???}); ???socket.on(‘chatOne‘, function(data) { ???????output(‘<span class="username-msg">‘+‘<img ?src="images/head.jpg" height="64" width="64"/>‘ + data.userName + ‘ : </span>‘ ???????????????+ data.content); ???????//editor.setData(""); ???????//editor.updateElement(); ???}); ???socket.on(‘disconnect‘,function() { ???????serverOutput(‘<span class="disconnect-msg">‘+$("#name").val()+‘已下线! </span>‘); ???});}function reloadThis(){ ???socket.disconnect(); ???connect(); ???console.log(socket);}function sendDisconnect() { ???socket.emit(‘chatOne‘, { ???????userId:1, ???????userName : $("#name").val(), ???????receiveUserId:2, ???????content : "已下线!" ???}); ???socket.disconnect();}function sendMessage() { ???var userName = $("#name").val() ???var message = editor.getData(); ???$(‘#msg‘).val(‘‘); ???socket.emit(‘chatOne‘, { ???????userId:1, ???????userName : userName, ???????receiveUserId:2, ???????content : message ???}); ???//editor.setData("");}function output(message) { ???var currentTime = "<span class=‘time‘ >" + new Date() + "</span>"; ???var element = $("<div>" +" " ?+ message + "</div>"); ???$(‘#console‘).prepend(element);}function serverOutput(message){ ???var element = $("<div>" + message + "</div>"); ???$(‘#console‘).prepend(element);}document.onkeydown=function(event){ ???//alert(0); ???var e = event || window.event || arguments.callee.caller.arguments[0]; ???if(event.ctrlKey&&event.keyCode==13){ // enter 键 ???????//要做的事情 ???????sendMessage(); ???}}; </script></html>
聊天室页面
<!DOCTYPE html><html><head><meta charset="GB2312"><title>小张唠嗑</title><base><script src="jquery-1.9.1.js" type="text/javascript"></script><script type="text/javascript" src="socket.io.js"></script><script src="ckeditor/ckeditor.js"></script><style>body { ???padding: 20px;}#console { ???height: 450px; ???overflow: auto;}.username-msg { ???color: orange;}.connect-msg { ???color: green;}.disconnect-msg { ???color: red;}.send-msg { ???color: #888}</style></head><body> ???<h1>老宋陪您唠嗑</h1> ???<!-- <br /> --> ???<div id="console" class="well"></div> ???<form class="well form-inline" onsubmit="return false;"> ???????<input id="name" ?class="input-xlarge" type="hidden" placeholder="用户名称. . . " /> ???????<!-- <input id="msg" class="input-xlarge" type="text" placeholder="发送内容. . . " /> --> ???????<textarea id="msg" rows="10" cols="50" placeholder="发送内容. . . "></textarea> ???????<button type="button" onClick="sendMessage()" class="btn">发送</button> ???????<button type="button" onClick="sendDisconnect()" class="btn">下线</button> ???????<button type="button" onClick="reloadThis()" class="btn">重连</button> ???</form></body><script type="text/javascript">var editor = CKEDITOR.replace( ‘msg‘ );editor.on("instanceReady",function(){ ???/* this.document.onkeydown=function(event){ ????????alert(0); ????????var e = event || window.event || arguments.callee.caller.arguments[0]; ????????if(event.ctrlKey&&event.keyCode==13){ // enter 键 ????????????//要做的事情 ????????????paraent.sendMessage(); ????????} ???}; ?*/ ???this.document.on("keydown",function(){ ???????//console.log(window.frames[0]); ???????var event = window.frames[0].event; ?????????if(event.ctrlKey&&event.keyCode==13){ // enter 键 ????????????//要做的事情 ???????????sendMessage(); ????????} ????});});var socket;connect();//var socket = io.connect(‘http://192.168.0.207:9092‘);function connect(){ ???socket = io.connect(‘ws://127.0.0.1:9092‘); ???$("#name").val("你的小宝贝儿"+parseInt(Math.random()*100+1, 10)); ???socket.on(‘connect‘,function() { ???????serverOutput(‘<span class="connect-msg">欢迎进入小张唠嗑聊天室!</span>‘); ???????//serverOutput(‘<span class="disconnect-msg">‘+$("#name").val()+‘已上线! </span>‘); ???????socket.emit(‘chatMany‘, { ???????????userId:1, ???????????userName : $("#name").val(), ???????????receiveUserId:2, ???????????content : "已上线!" ???????}); ???}); ???socket.on(‘chatMany‘, function(data) { ???????output(‘<span class="username-msg">‘+‘<img ?src="images/head.jpg" height="64" width="64"/>‘ + data.userName + ‘ : </span>‘ ???????????????+ data.content); ???????//editor.setData(""); ???????//editor.updateElement(); ???}); ???socket.on(‘disconnect‘,function() { ???????serverOutput(‘<span class="disconnect-msg">‘+$("#name").val()+‘已下线! </span>‘); ???});}function reloadThis(){ ???socket.disconnect(); ???connect(); ???console.log(socket);}function sendDisconnect() { ???socket.emit(‘chatMany‘, { ???????userId:1, ???????userName : $("#name").val(), ???????receiveUserId:2, ???????content : "已下线!" ???}); ???socket.disconnect();}function sendMessage() { ???var userName = $("#name").val() ???var message = editor.getData(); ???$(‘#msg‘).val(‘‘); ???socket.emit(‘chatMany‘, { ???????userId:1, ???????userName : userName, ???????receiveUserId:2, ???????content : message ???}); ???//editor.setData("");}function output(message) { ???var currentTime = "<span class=‘time‘ >" + new Date() + "</span>"; ???var element = $("<div>" +" " ?+ message + "</div>"); ???$(‘#console‘).prepend(element);}function serverOutput(message){ ???var element = $("<div>" + message + "</div>"); ???$(‘#console‘).prepend(element);}document.onkeydown=function(event){ ???//alert(0); ???var e = event || window.event || arguments.callee.caller.arguments[0]; ???if(event.ctrlKey&&event.keyCode==13){ // enter 键 ???????//要做的事情 ???????sendMessage(); ???}}; </script></html>
源码链接
netty-socket.io点对点通讯和聊天室通讯
原文地址:https://www.cnblogs.com/MrSong97/p/8509453.html