参考:基于netty-socketio的web推送服务、Spring Boot实战之netty-socketio实现简单聊天室(给指定用户推送消息)、socket.io 中文文档
socketio简介
Socket.io是一个WebSocket库,包括了客户端的js和服务器端的nodejs,它的目标是构建可以在不同浏览器和移动设备上使用的实时应用。它会自动根据浏览器从WebSocket、AJAX长轮询、Iframe流等等各种方式中选择最佳的方式来实现网络实时应用,非常方便和人性化,而且支持的浏览器最低达IE5.5.
socket.io特点
实时分析:将数据推送到客户端,这些客户端会被表示为实时计数器,图表或日志客户。
实时通信和聊天:只需几行代码便可写成一个Socket.IO的”Hello,World”聊天应用。
二进制流传输:从1.0版本开始,Socket.IO支持任何形式的二进制文件传输,例如:图片,视频,音频等。
文档合并:允许多个用户同时编辑一个文档,并且能够看到每个用户做出的修改。
服务端使用netty-socketio,客户端使用socket.io.js。
本例完全来自上面的链接,这里只是测试效果以及做备忘。本例实现的功能是一个用户向另外一个用法发小消息。
<dependency>
<groupId>com.corundumstudio.socketiogroupId>
<artifactId>netty-socketioartifactId>
<version>1.7.3version>
dependency>
@Component
public class ChatServer implements InitializingBean {
@Autowired
private EventListenner eventListenner;
@Override
public void afterPropertiesSet() throws Exception {
Configuration config = new Configuration();
config.setPort(9098);
SocketConfig socketConfig = new SocketConfig();
socketConfig.setReuseAddress(true);
socketConfig.setTcpNoDelay(true);
socketConfig.setSoLinger(0);
config.setSocketConfig(socketConfig);
config.setHostname("localhost");
SocketIOServer server = new SocketIOServer(config);
server.addListeners(eventListenner);
server.start();
System.out.println("启动正常");
}
}
@Component("clientCache")
public class SocketIOClientCache {
//String:EventType类型
private Map clients=new ConcurrentHashMap();
//用户发送消息添加
public void addClient(SocketIOClient client,MsgBean msgBean){
clients.put(msgBean.getFrom(),client);
}
//用户退出时移除
public void remove(MsgBean msgBean) {
clients.remove(msgBean.getFrom());
}
//获取所有
public SocketIOClient getClient(String to) {
return clients.get(to);
}
}
@Service("socketIOResponse")
public class SocketIOResponse {
public void sendEvent(SocketIOClient client, MsgBean bean) {
System.out.println("推送消息");
client.sendEvent("OnMSG", bean);
}
}
@Service("eventListenner")
public class EventListenner {
@Resource(name = "clientCache")
private SocketIOClientCache clientCache;
@Resource(name = "socketIOResponse")
private SocketIOResponse socketIOResponse;
@OnConnect
public void onConnect(SocketIOClient client) {
System.out.println("建立连接");
}
@OnEvent("OnMSG")
public void onSync(SocketIOClient client, MsgBean bean) {
System.out.printf("收到消息-from: %s to:%s\n", bean.getFrom(), bean.getTo());
clientCache.addClient(client, bean);
SocketIOClient ioClients = clientCache.getClient(bean.getTo());
System.out.println("clientCache");
if (ioClients == null) {
System.out.println("你发送消息的用户不在线");
return;
}
socketIOResponse.sendEvent(ioClients,bean);
}
@OnDisconnect
public void onDisconnect(SocketIOClient client) {
System.out.println("关闭连接");
}
}
public class MsgBean {
private String from;
private String to;
private String content;
public String getFrom() {
return from;
}
public void setFrom(String from) {
this.from = from;
}
public String getTo() {
return to;
}
public void setTo(String to) {
this.to = to;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
@Override
public String toString() {
return "MsgBean [from=" + from + ", to=" + to + ", content=" + content + "]";
}
}
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
<head>
<title>socket.io demotitle>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<script type="text/javascript" th:src="@{/js/jquery.js}">script>
<script type="text/javascript" th:src="@{/js/socket.io.min.js}">script>
<style>
body {
padding: 20px;
}
#console {
height: 400px;
overflow: auto;
}
.username-msg {
color: orange;
}
.connect-msg {
color: green;
}
.disconnect-msg {
color: red;
}
.send-msg {
color: #888
}
style>
head>
<body>
<h1>Netty-socketio chat demoh1>
<br />
<div id="console" class="well">div>
<form class="well form-inline" onsubmit="return false;">
<input id="from" class="input-xlarge" type="text" placeholder="from. . . " />
<input id="to" class="input-xlarge" type="text" placeholder="to. . . " />
<input id="content" class="input-xlarge" type="text" placeholder="content. . . " />
<button type="button" onClick="sendMessage()" class="btn">Sendbutton>
<button type="button" onClick="sendDisconnect()" class="btn">Disconnectbutton>
form>
body>
<script type="text/javascript">
var socket = io.connect('http://localhost:9098');
socket.on('connect',function() {
output('Client has connected to the server!');
});
socket.on('OnMSG', function(data) {
output('' + data.content + ' : ');
});
socket.on('disconnect',function() {
output('The client has disconnected! ');
});
function sendDisconnect() {
socket.disconnect();
}
function sendMessage() {
var from = $("#from").val();
var to = $("#to").val();
var content = $('#content').val();
socket.emit('OnMSG', {
from : from,
to : to,
content : content
});
}
function output(message) {
console.log(message)
var currentTime = "" + new Date() + "";
var element = $("" + currentTime + " " + message + "
");
$('#console').prepend(element);
}
script>
html>
说明:工程基于springboot,关于springboot相关的内容并未给出。
浏览器2个标签页分页输入地址,进入到聊天页面。
标签页1
我们假定标签页1用户为admin,标签页2用户为test。
标签页1:admin向test发送1条消息,点击发送,切换到标签页2,发现并没有消息。因为这个时候缓存中没有test,所以没有发送成功。
标签页2:test向admin发送1条消息。
切换到标签页1,可以发现已经接受到test发送的消息
我们F12打开开发人员工具,可以看到多次发送消息并没有产生新的请求。
1.中文乱码
尚未找到解决方案。
netty-socketio:https://github.com/mrniko/netty-socketio
netty-socketio-demo:https://github.com/mrniko/netty-socketio-demo