html面页与JAVA通过webSocket 通讯
(原)
往常前后端通讯基本都是以ajax请求或是表单做数据交互的,这是一种无状态的http协议,如果要做tcp协议的数据交互,能想到的技术也就socket了,可如果后端是JAVA,前端如何做socket呢,在html5出来之前,只能用ajax轮询,html5中有定义了一个新的数据传输协议,webSocket,这是一种长连接协议,类似于socket,html5出来好些年了,基本主流浏览器的最新版本都支持,在js中用window.WebScoket就可以得到它,它的API很简单,这里暂不介绍,这里介绍一下对其封装的一个第三方js库,socket.io,下面来看看如何实现吧。
1、你必需知道socket.io实际上就是一个js文件,它可以在这下载。(https://github.com/socketio/socket.io-client)

上面也写的很清楚了,最简单的使用方法,也就几行代码。
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.这里就以最新版本以例。
先写前端。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>demo</title>
<script src="js/jquery/jquery-1.8.3.min.js" type="text/javascript"></script>
<script type="text/javascript" src="js/socket.io/socket.io.js"></script> </head>
<body> </body>
<script type="text/javascript">
//创建TCP连接
var socket = io.connect('http://192.168.0.104:8998');
//连接成功后会监听到
socket.on('connect',function() {
output('<span>连接成功</span>');
}); socket.on('connecting',function() {
output('<span>正在连接...</span>');
}); socket.on('disconnect',function() {
output('<span>断开连接! </span>');
}); socket.on('reconnecting',function() {
output('<span>正在重连...</span>');
}); socket.on('reconnect',function() {
output('<span>成功重连!</span>');
}); socket.on('connect_failed',function() {
output('<span>连接失败!</span>');
}); //想要断开连接调用此方法
function sendDisconnect() {
socket.disconnect();
}
//下面的testMessage是自定义的。
socket.emit('testMessage', 'Hello',function(){
output('<span>' + data + '</span>');
});
//socket.emit('testMessage', '你好',function(){
// output('<span>' + data + '</span>');
//});
//这里是监听服务端返回的testMessage事件
//socket.on('testMessage',function(data){
// output('<span>' + data + '</span>');
//}); function output(message) {
var currentTime = "<span class='time' >" + new Date().toLocaleString() + "</span>";
var element = $("<div>" + currentTime + " " + message + "</div>");
$('body').prepend(element);
} </script>
</html>
我们叫这个页面为demo.html
然后再写JAVA后端
只需要二个类,一个是开启socket服务的类,一个是监听的类,这里只监听客户端的连接,断开和发送testMessage消息。
package com.ewin.ccr; import com.corundumstudio.socketio.AckRequest;
import com.corundumstudio.socketio.SocketIOClient;
import com.corundumstudio.socketio.SocketIOServer;
import com.corundumstudio.socketio.listener.ConnectListener;
import com.corundumstudio.socketio.listener.DataListener;
import com.corundumstudio.socketio.listener.DisconnectListener; public class SocketListener implements ConnectListener ,DisconnectListener,DataListener<String>{
private SocketIOServer server; public SocketListener(SocketIOServer server){
this.server = server;
} @Override
public void onConnect(SocketIOClient client) {
Integer clientSize = server.getAllClients().size();
System.out.println("刚连上一个客户端,总共有" + clientSize + "客户端连接成功。");
} @Override
public void onDisconnect(SocketIOClient client) {
Integer clientSize = server.getAllClients().size();
System.out.println("刚离开一个客户端,总共有" + clientSize + "客户端连接成功。");
} @Override
public void onData(SocketIOClient client, String data, AckRequest ackSender)
throws Exception {
System.out.println("刚有一个数据从客户端过来" + data);
ackSender.sendAckData("服务端消息收到!-----");
} }
以上为监听类
package com.ewin.ccr; import com.corundumstudio.socketio.Configuration;
import com.corundumstudio.socketio.SocketIOServer;
import com.ewin.ccr.util.SocketConfig; public class SocketServer { public static void main(String[] args) {
Configuration config = new Configuration();
config.setHostname(SocketConfig.getValue("host"));
config.setPort(Integer.parseInt(SocketConfig.getValue("port")));
SocketIOServer server = new SocketIOServer(config); SocketListener socketListener = new SocketListener(server); //客户端连接上时触发
server.addConnectListener(socketListener); //监听客户端消息
//工单产品执行监控表头数据,只发一次,需要由客户端请求后发送
server.addEventListener("testMessage", String.class, new socketListener()); //客户断连接断开时触发
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秒以上再发送消息 ,后面收到中文的概率已经很大了),后面再发送都不会有这个问题。
html面页与JAVA通过webSocket 通讯的更多相关文章
- Java用WebSocket + tail命令实现Web实时日志
原文:http://blog.csdn.net/xiao__gui/article/details/50041673 在Linux操作系统中,经常需要查看日志文件的实时输出内容,通常会使用tail - ...
- java 实现websocket
最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向 ...
- websocket通讯协议(10版本)简介
前言: 工作中用到了websocket 协议10版本的,英文的协议请看这里: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotoc ...
- Java和WebSocket开发网页聊天室
小编心语:咳咳咳,今天又是聊天室,到现在为止小编已经分享了不下两个了,这一次跟之前的又不大相同,这一次是网页聊天室,具体怎么着,还请各位看官往下看~ Java和WebSocket开发网页聊天室 一.项 ...
- Java 线程间通讯(管道流方式)
一.管道流是JAVA中线程通讯的常用方式之一,基本流程如下: 1)创建管道输出流PipedOutputStream pos和管道输入流PipedInputStream pis 2)将pos和pis匹配 ...
- Java 线程间通讯(共享变量方式)
Java线程间通讯,最常用的方式便是共享变量方式,多个线程共享一个静态变量就可以实现在线程间通讯,但是这需要注意的就是线程同步问题. 一.没考虑线程同步: package com.wyf; publi ...
- 基于Java的WebSocket推送
WebSocket的主动推送 关于消息推送,现在的解决方案如轮询.长连接或者短连接,当然还有其他的一些技术框架,有的是客户端直接去服务端拿数据. 其实推送推送主要讲的是一个推的概念,WebSocket ...
- webSocket通讯
1.使用facebook第三方SRWebSocket进行websocket通讯. pod 'SocketRocket' 2.通讯地址: ws://192.168.1.128:18882/ws 注意:s ...
- java 实现websocket的三种方式
Java中实现websocket常见有以下三种方式: 使用tomcat的websocket实现,需要tomcat 7.x,JEE7的支持. 使用spring的websocket,spring与webs ...
随机推荐
- [PHP] 理解依赖注入
两个类有依赖关系的时候 使用者通过构造函数参数,方法或属性等方式将具体组件,传给自己 $storage=new Storge(); //构造函数注入 class User{ public functi ...
- Tomcat服务器为java项目配置顶级域名
修改端口, Tomcat服务器下conf/server.xml文件 把端口号更改为80 解释:输入域名时默认进入80端口,如果没修改则需要输入端口号才能进入. Eg:www.xxx.com: ...
- Java 控制类的引用类型,合理使用内存
Java提供了 java.lang.ref包,该包下的类均与垃圾回收机制相关 先介绍Java对象的集中引用类型 1.强引用 强引用是最常见的,创建对象就是强引用,如 String a = new St ...
- javascript 动态修改css样式
方法一:改变外联css文件,这里不讲这个. 方法二:通过改变claaName来改变样式,语法: obj.className = "style2"; //或者 obj.setAttr ...
- Android view显示在软键盘上方
给EditText外加一个ScrollView,将高度设置统一,并给ScrollView设置属性 android:fillViewport="true". 注:ScrollVie ...
- 真实世界的脉络].(英)戴维.多伊奇.pdf
[真实世界的脉络].(英)戴维.多伊奇.pdf 宇宙.时间.生命.等等,如果用量子物理学.计算机科学.进化论.认识论将这些最基本而又复杂的问题纠缠在一起时,那将会是一幅什么样的图景呢?也许,我们穷尽一 ...
- box-sizing 的作用
box-sizing:content-box | border-box content-box: padding和border不被包含在定义的width和height之内.对象的实际宽度等于设置的wi ...
- 将HTML页面自动保存为PDF文件并上传的两种方式(一)-前端(react)方式
一.业务场景 公司的样本检测报告以React页面的形式生成,已调整为A4大小的样式并已实现分页,业务上需要将这个网页生成PDF文件,并上传到服务器,后续会将这个文件发送给客户(这里不考虑). 二.原来 ...
- Python高级特性:迭代
迭代的目的是实现遍历出一个可迭代对象的元素,即for循环 基本语法 : for ... in ... 首先只有可迭代对象才可以迭代,判断一个对象是不是可以迭代的方法如下: >>> f ...
- Android JNI中C调用Java方法
背景需求 我们需要在JNI的C代码调用Java代码.实现原理:使用JNI提供的反射借口来反射得到Java方法,进行调用. JNI关键方法讲解. 1. 在同一个类中,调用其他方法 JNIEXPORT v ...