(原)

往常前后端通讯基本都是以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 通讯的更多相关文章

  1. Java用WebSocket + tail命令实现Web实时日志

    原文:http://blog.csdn.net/xiao__gui/article/details/50041673 在Linux操作系统中,经常需要查看日志文件的实时输出内容,通常会使用tail - ...

  2. java 实现websocket

    最近了解了下websocket和socket这个东西,说不得不来说下为何要使用 WebSocket ,和为何不用http. 为何需要WebSocket ? HTTP 协议是一种无状态的.无连接的.单向 ...

  3. websocket通讯协议(10版本)简介

    前言: 工作中用到了websocket 协议10版本的,英文的协议请看这里: http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotoc ...

  4. Java和WebSocket开发网页聊天室

    小编心语:咳咳咳,今天又是聊天室,到现在为止小编已经分享了不下两个了,这一次跟之前的又不大相同,这一次是网页聊天室,具体怎么着,还请各位看官往下看~ Java和WebSocket开发网页聊天室 一.项 ...

  5. Java 线程间通讯(管道流方式)

    一.管道流是JAVA中线程通讯的常用方式之一,基本流程如下: 1)创建管道输出流PipedOutputStream pos和管道输入流PipedInputStream pis 2)将pos和pis匹配 ...

  6. Java 线程间通讯(共享变量方式)

    Java线程间通讯,最常用的方式便是共享变量方式,多个线程共享一个静态变量就可以实现在线程间通讯,但是这需要注意的就是线程同步问题. 一.没考虑线程同步: package com.wyf; publi ...

  7. 基于Java的WebSocket推送

    WebSocket的主动推送 关于消息推送,现在的解决方案如轮询.长连接或者短连接,当然还有其他的一些技术框架,有的是客户端直接去服务端拿数据. 其实推送推送主要讲的是一个推的概念,WebSocket ...

  8. webSocket通讯

    1.使用facebook第三方SRWebSocket进行websocket通讯. pod 'SocketRocket' 2.通讯地址: ws://192.168.1.128:18882/ws 注意:s ...

  9. java 实现websocket的三种方式

    Java中实现websocket常见有以下三种方式: 使用tomcat的websocket实现,需要tomcat 7.x,JEE7的支持. 使用spring的websocket,spring与webs ...

随机推荐

  1. 【译】《Clean C#》

    本文是<Clean C#>一书译文的序言,阅读译文请移步至:<Clean C#>译文. <Clean C#>的副标题是Readable,Maintainable,P ...

  2. java使用POI将数据导出放入Excel

    本文主要是将数据库取出的数据按照自定义的行列格式导出到excel中,POI则是实现我们需求所用到的技术. POI介绍 使用spring boot导入相关依赖 获取数据(自行处理) 完整代码实例:创建e ...

  3. hihoCoder编程练习赛70

    题目1 : 数位翻转 时间限制:20000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个数 n,你可以进行若干次操作,每次操作可以翻转 n 的二进制表示下的某一位,即将 0 变成 ...

  4. linux防火墙相关 iptables

    1. root用户查看防火墙状态(非root用户无权限查看) 查看防火墙状态: service iptables status 2.开启和关闭防火墙 //开启防火墙: service iptables ...

  5. 如何将字符串格式的对象转换成真正的js对象?

    1.如何将字符串格式的对象转换成真正的js对象? <script>//eval 的作用eval('var a = 100');console.log(a);</script> ...

  6. JavaScript Hoisting(提升)

    Hoisting 是指 js 在执行代码前,默认会将变量的声明和函数的声明,提升到当前作用域顶端的行为. 这里要注意一下,只提升声明,例如: console.log(a); var a = 10; / ...

  7. Jenkins Jenkins结合GIT Maven持续集成环境配置

    Jenkins结合GIT Maven持续集成环境配置   by:授客 QQ:1033553122 安装Git插件 1 安装Git客户端 1 安装JAVA JDK及MAVEN 2 Jenkins JDK ...

  8. ScrollView嵌套ListView、GridView,进入页面显示的位置并不是在最顶部,而是在中间部分问题

    在Android项目的开发中,经常会遇到一些布局,可能需要在ScrollView中嵌套ListView或.GridView来实现, 是在使用的过程总又遇到了一个新的问题,就是如果在ScrollView ...

  9. Flutter 布局(一)- Container详解

    本文主要介绍Flutter中非常常见的Container,列举了一些实际例子介绍如何使用. 1. 简介 A convenience widget that combines common painti ...

  10. CsQuery获取IDomObject元素的完整CSS选择器

    一.方法说明 通过IDomObject元素,获取完整的CSS选择器,过滤HTML和BODY元素,自动将class.id添加到选择器上,优先添加class,无class再添加id.如: <html ...