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="data: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="data: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点对点通讯和聊天室通讯的更多相关文章

  1. 利用socket.io+nodejs打造简单聊天室

    代码地址如下:http://www.demodashi.com/demo/11579.html 界面展示: 首先展示demo的结果界面,只是简单消息的发送和接收,包括发送文字和发送图片. ws说明: ...

  2. html5的新通讯技术socket.io,实现一个聊天室

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  3. vue + socket.io实现一个简易聊天室

    vue + vuex + elementUi + socket.io实现一个简易的在线聊天室,提高自己在对vue系列在项目中应用的深度.因为学会一个库或者框架容易,但要结合项目使用一个库或框架就不是那 ...

  4. 基于Node.js+socket.IO创建的Web聊天室

    这段时间进了一个新的项目组,项目是用Appcan来做一个跨平台的移动运维系统,其中前台和后台之间本来是打算用WebSocket来实现的,但写好了示例后发现android不支持WebSocket,大为受 ...

  5. 基于react+react-router+redux+socket.io+koa开发一个聊天室

    最近练手开发了一个项目,是一个聊天室应用.项目虽不大,但是使用到了react, react-router, redux, socket.io,后端开发使用了koa,算是一个比较综合性的案例,很多概念和 ...

  6. 利用socket.io实现多人聊天室(基于Nodejs)

    socket.io简单介绍 在Html5中存在着这种一个新特性.引入了websocket,关于websocket的内部实现原理能够看这篇文章.这篇文章讲述了websocket无到有,依据协议,分析数据 ...

  7. 【Spring Boot】集成Netty Socket.IO通讯框架

    服务端 @Configuration public class NettySocketConfig { private static final Logger logger = LoggerFacto ...

  8. Netty学习笔记(六) 简单的聊天室功能之WebSocket客户端开发实例

    在之前的Netty相关学习笔记中,学习了如何去实现聊天室的服务段,这里我们来实现聊天室的客户端,聊天室的客户端使用的是Html5和WebSocket实现,下面我们继续学习. 创建客户端 接着第五个笔记 ...

  9. Netty学习笔记(四) 简单的聊天室功能之服务端开发

    前面三个章节,我们使用了Netty实现了DISCARD丢弃服务和回复以及自定义编码解码,这篇博客,我们要用Netty实现简单的聊天室功能. Ps: 突然想起来大学里面有个课程实训,给予UDP还是TCP ...

随机推荐

  1. join() 和 sleep() 区别

    来源于<Java多线程编程核心技术> 一.join() 作用 在很多情况,主线程创建并启动子线程,如果子线程中需要进行大量的耗时计算,主线程往往早于子线程结束.这时,如果主线程想等待子线程 ...

  2. 关于docker remote api未授权访问漏洞的学习与研究

    漏洞介绍: 该未授权访问漏洞是因为docker remote api可以执行docker命令,从官方文档可以看出,该接口是目的是取代docker 命令界面,通过url操作docker. docker ...

  3. 【转载】了解CSS/CSS3原生变量var

    文章转载自:鑫空间鑫生活(https://www.zhangxinxu.com/) 原文链接:http://www.zhangxinxu.com/wordpress/?p=5804 内容摘要: 在任何 ...

  4. 从零开始的全栈工程师——js篇2.20(事件对象 冒泡与捕获)

    一.复习 面向对象 1)单例模式 2)工厂模式 3)构造函数 ①类js天生自带的类 基类object function array number math boolean date regexp st ...

  5. laravel安装时openssl_encrypt() 的问题?Call to undefined function openssl_decrypt()

    解决方案: 如果通过上面的步骤还是不能解决参考如下: 1.从php安装根目录中拷贝 libeay32.dll 和 ssleay32.dll 然后 覆盖掉apache/bin 下的对应文件(注意需要将h ...

  6. ArcGIS几种数据格式2

    各种数据的组织形式不一样,其中shp.Coverage.Raster.CAD为文件类型,Geodatabase为空间数据库.Workstaion常用Coverage数据格式.现在ESRI公司推荐使用G ...

  7. Android Studio快捷键【Android学习入门】

    Studio快捷键[Android学习入门]" title="Android Studio快捷键[Android学习入门]"> 提示 Ctrl+P方法参数提示 Ct ...

  8. SpringCloud的学习记录(5)

    这一章节讲如何使用ribbon和hystrix. 在我们生成的Demo项目上右键点击New->Module->spring Initializr, 然后next, 填写Group和Arti ...

  9. C++常用字符串分割方法(转)

    1.用strtok函数进行字符串分割 原型: char *strtok(char *str, const char *delim); 功能:分解字符串为一组字符串. 参数说明:str为要分解的字符串, ...

  10. Linq to Sql 左连接 , 取右表可能为 null的 int类型字段

    linq to sql , linq to entity 遇到一个问题, 主表, 从表 一对一 关系,  主表有记录, 从表 可能没有记录. 现在要查询 主表+从表 的某几个字段. 从表字段 有的是 ...