(原)
往常前后端通讯基本都是以ajax请求或是表单做数据交互的,这是一种无状态的http协议,如果要做tcp协议的数据交互,能想到的技术也就socket了,可如果后端是JAVA,前端如何做socket呢,在html5出来之前,只能用ajax轮询,html5中有定义了一个新的数据传输协议,webSocket,这是一种长连接协议,类似于socket,html5出来好些年了,基本主流浏览器的最新版本都支持,在js中用window.WebScoket就可以得到它,它的API很简单,这里暂不介绍,这里介绍一下对其封装的一个第三方js库,socket.io,下面来看看如何实现吧。
上面也写的很清楚了,最简单的使用方法,也就几行代码。
2、你需要知道JAVA端怎么写最方便,实现已经有第三方针对于socket.io完成了JAVA端的实现,只用引入JAR包,调用相应的API就行了,它跟socket.io有个相对应的名字,叫netty-socketio。它可以在这里下载。(https://github.com/mrniko/netty-socketio)
它的文档里也写了一大堆,实际上你如果要最快的上手,只需要这一句话就够了。
netty-socketio的1.6.6版本支持socket.io1.0以下的版本,最新版的netty-socketio支持1.0以上的socket.io版本。
(别混了概念,netty-socketio指的是JAVA端的一个JAR,socket.io指的是一个JS文件)
3.这里就以最新版本以例。
先写前端。
demo//创建TCP连接
var socket = io.connect('http://192.168.0.104:8998');
//连接成功后会监听到
socket.on('connect',function() {
output('连接成功');
});
socket.on('connecting',function() {
output('正在连接...');
});
socket.on('disconnect',function() {
output('断开连接! ');
});
socket.on('reconnecting',function() {
output('正在重连...');
});
socket.on('reconnect',function() {
output('成功重连!');
});
socket.on('connect_failed',function() {
output('连接失败!');
});
//想要断开连接调用此方法
function sendDisconnect() {
socket.disconnect();
}
//下面的testMessage是自定义的。
socket.emit('testMessage', 'Hello',function(){
output('' + data + '');
});
//socket.emit('testMessage', '你好',function(){
//output('' + data + '');
//});
//这里是监听服务端返回的testMessage事件
//socket.on('testMessage',function(data){
// output('' + data + '');
//});
function output(message) {
var currentTime = "" + new Date().toLocaleString() + "";
var element = $("
$('body').prepend(element);
}
我们叫这个页面为demo.html
然后再写JAVA后端
只需要二个类,一个是开启socket服务的类,一个是监听的类,这里只监听客户端的连接,断开和发送testMessage消息。
packagecom.ewin.ccr;importcom.corundumstudio.socketio.AckRequest;importcom.corundumstudio.socketio.SocketIOClient;importcom.corundumstudio.socketio.SocketIOServer;importcom.corundumstudio.socketio.listener.ConnectListener;importcom.corundumstudio.socketio.listener.DataListener;importcom.corundumstudio.socketio.listener.DisconnectListener;public class SocketListener implements ConnectListener ,DisconnectListener,DataListener{privateSocketIOServer server;publicSocketListener(SocketIOServer server){this.server =server;
}
@Overridepublic voidonConnect(SocketIOClient client) {
Integer clientSize=server.getAllClients().size();
System.out.println("刚连上一个客户端,总共有" + clientSize + "客户端连接成功。");
}
@Overridepublic voidonDisconnect(SocketIOClient client) {
Integer clientSize=server.getAllClients().size();
System.out.println("刚离开一个客户端,总共有" + clientSize + "客户端连接成功。");
}
@Overridepublic voidonData(SocketIOClient client, String data, AckRequest ackSender)throwsException {
System.out.println("刚有一个数据从客户端过来" +data);
ackSender.sendAckData("服务端消息收到!-----");
}
}
以上为监听类
packagecom.ewin.ccr;importcom.corundumstudio.socketio.Configuration;importcom.corundumstudio.socketio.SocketIOServer;importcom.ewin.ccr.util.SocketConfig;public classSocketServer {public static voidmain(String[] args) {
Configuration config= newConfiguration();
config.setHostname(SocketConfig.getValue("host"));
config.setPort(Integer.parseInt(SocketConfig.getValue("port")));
SocketIOServer server= newSocketIOServer(config);
SocketListener socketListener= newSocketListener(server);//客户端连接上时触发
server.addConnectListener(socketListener);//监听客户端消息//工单产品执行监控表头数据,只发一次,需要由客户端请求后发送
server.addEventListener("testMessage", String.class, newsocketListener());//客户断连接断开时触发
server.addDisconnectListener(socketListener);//启动服务
server.start();//server.stop();
}
}
以上为开启socket服务的类
运行SocketServer这个类
然后进入我们的demo页面,你会看到如下信息
后台会是这样的。
然后我们尝试关闭页面。后台会变成这样。
我们尝试关掉JAVA服务,页面会变成这样。
其实,这还没完,这里不知是BUG,还是什么原因,会有一个问题。
看到页面这个地方没有
现在我们来换一下,发送一个中文的"你好"给后台,我们需要把上面的注释取消,把下面的注释放开,改成这样
然后我们把demo.html页面刷新一下,关掉,再重开(这样是为了使修改的JS生效)
OK,前面没有问题,再看下我们的二个中文字“你好”过去没有。
看到没,后端是乱码,估计这种问题的第一反应,可能绝大数程序员想的跟我一样,转码出了问题,于是各种前后端编码,字符集的检查,但是你会发现,以前出现这种问题时,能用上的转码,切换字符集的招数都用遍了, 这里依然无效。
经过我一天的摸索,得到一个好消息与一个坏消息。
先说坏的,百度有人说是socket.io版本不够新,今天是2017年6月4号,最新版是6月2号的2.0.2版本,我试了一下最新的,问题依然存在。
好消息是我找到了问题的解决办法,但是过于暴力。
看下面这段代码:
跟刚才的本质没有变,只是延迟0.5秒发送消息,我们再次刷新demo.html页面,来看下后台的反应。
看到没,中文传送过来了。
那有人可能就要问了,如果做一个即时通讯之类的,那岂不是每次发送消息都要等上半秒钟,其实不是这样的,经过我多次的测试,只有在连接刚建立完成以后的一小段时间内发送中文才会有这个问题(上面其实是连建立后等了0.5秒发送的消息,实际上测的是延迟0.2秒以上再发送消息 ,后面收到中文的概率已经很大了),后面再发送都不会有这个问题。