本文来自作者
蓝天
在
GitChat
上分享 「Socket.IO 入门」,
「
阅读原文
」
查看交流实录。
「
文末高能
」
编辑 | 哈比
1. Socket.IO 原理
node.js 提供了高效的服务端运行环境,但是由于浏览器端对 HTML5 的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验,于是 socket.io 诞生。
Socket.io 将 Websocket 和轮询 (Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。
也就是说,Websocket 仅仅是 Socket.io 实现实时通信的一个子集。那么,Socket.io 都实现了 Polling 中的那些通信机制呢?
WebSocket
Adobe® Flash® Socket
AJAX long polling
AJAX multipart streaming
Forever Iframe
JSONP Polling
Adobe® Flash® Socket 大部分 PC 浏览器都支持的 socket 模式,不过是通过第三方嵌入到浏览器,不在 W3C 规范内,所以可能将逐步被淘汰,况且,大部分的手机浏览器都不支持这种模式。
AJAX long polling 这个很好理解,所有浏览器都支持这种方式,就是定时的向服务器发送请求,缺点是会给服务器带来压力并且出现信息更新不及时的现象。
AJAX multipart streaming 这是在 XMLHttpRequest 对象上使用某些浏览器(比如说 Firefox)支持的 multi-part 标志。
Ajax 请求被发送给服务器端并保持打开状态(挂起状态),每次需要向客户端发送信息,就寻找一个挂起的的 http 请求响应给客户端,并且所有的响应都会通过统一连接来写入。
var xhr = \$.ajaxSettings.xhr();
xhr.multipart =true;
xhr.open('GET', 'ajax', true);
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
processEvents($.parseJSON(xhr.responseText));
}
};
xhr.send(null);
Forever Iframe (永存的 Iframe)技术涉及了一个置于页面中的隐藏 Iframe 标签,该标签的 src 属性指向返回服务器端事件的 servlet 路径。
每次在事件到达时,servlet 写入并刷新一个新的 script 标签,该标签内部带有 JavaScript 代码,iframe 的内容被附加上这一 script 标签,标签中的内容就会得到执行。
这种方式的缺点是接和数据都是由浏览器通过 HTML 标签来处理的,因此你没有办法知道连接何时在哪一端已被 断开了,并且 Iframe 标签在浏览器中将被逐步取消使用。
JSONP Polling JSONP 轮询基本上与 HTTP 轮询一样,不同之处则是 JSONP 可以发出跨域请求,详细请搜索查询 jsonp 的内容。
2. Socket.IO 环境搭建
本次给大家带来两种使用 Socket.IO 的方法。
两种方法都需要安装 JDK,JDK 版本要求 1.7 以上,JDK 安装方法就不说了,网上有很多
使用 Node.js 运行 Socket.IO
首先我们需要下载 Node.js 并安装。
这次我下载的是 9.2.0 Current 版本。
我安装的目录是——-
E:\Program Files\nodejs
这个目录是用来配置环境变量的。安装完成之后我们可以得到如下图这些文件。
这样我们还需要去配置环境变量。新建一个 NODEJS_HOME=E:\Program Files\nodejs。
在 Path 最后追加
%NODEJS_HOME%\
配置完成后我们验证一下 node.js 是否可用。打开 CMD,输入 node -v:
目前我们只是完成了 node.js 的安装。并无法使用 socket.io,因为 socket.io 只是 node.js 下的一个模块,需要我们手动安装。
如何安装呢?很简单。打开 CMD 直接输入 npm install socket.io 就可以自动的从网上把 socketio 下载下来了。
至此我们就将环境搭建完成了。
使用 Node.js 运行 socket.io
为了方便,我直接在桌面新建了一个文件夹 socketIOdemo。目录如下:
app.js 代码如下:
var app = require('http').createServer(handler)
, io = require('socket.io').listen(app)
, fs = require('fs')
app.listen(3000);function handler (req, res) {
fs.readFile(__dirname + '/index.html',function (err, data) {if (err) {
res.writeHead(500);return res.end('Error loading index.html');
}
res.writeHead(200);
res.end(data);
});
}io.sockets.on('connection', function (socket) { console.log(" 客户端连接 ");
socket.on('message', function (data) {console.log(data);
io.sockets.emit('chatevent', { userName: data.userName,message:data.message });
});
socket.on('disconnect',function(){console.log(' 客户端断开连接 ');
});
});console.log("success listening port:3000");
jquery-3.2.1.min.js 和 socket.io.js 请分别到网上下载。chat.html 代码如下:
<html><head> <meta http-equiv="Content-Type" content="text/html;" charset="UTF-8"> <title>Socketio chattitle> <script src="./js/jquery-3.2.1.min.js" type="text/javascript">script> <script type="text/javascript" src="./js/socket.io.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><h3>Netty-socketio chat demoh3><br /><div id="console" class="well">div><form class="well form-inline" onsubmit="return false;"> <input id="name" class="input-xlarge" type="text" placeholder=" 用户名称 . . . " /> <input id="msg" class="input-xlarge" style="width:500px;height:100px;" type="text" placeholder=" 发送内容 . . . " /> <button type="button" onClick="sendMessage()" class="btn"> 发送 button> <br />form>body><script type="text/javascript"> Date.prototype.Format = function (fmt) { var o = { "M+": this.getMonth() + 1, "d+": this.getDate(), "h+": this.getHours(), "H+": this.getHours(), "m+": this.getMinutes(), "s+": this.getSeconds(), "q+": Math.floor((this.getMonth() + 3) / 3), "S": this.getMilliseconds() }; if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length)); for (var k in o) if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length))); return fmt;
} var socket = io.connect('http://localhost:3000'); socket.on('connect',function() { output(' 客户端连接服务器 !'); }); socket.on('chatevent', function(data) { output('' + data.userName + ' : '+ data.message); }); socket.on('disconnect',function(data) { output(' 客户端已断开连接 ! '); }); function sendDisconnect() { socket.disconnect(); } function sendReconnect() { socket.reconnect(); } function sendMessage() { var userName = $("#name").val(); var message = $('#msg').val(); var chatDate = new Date(); $('#msg').val(''); socket.emit('message', { userName : userName, message : message }); } function output(message) { var currentTime = "" + new Date().Format("yyyy-MM-dd HH:mm:ss") + ""; var element = $("
" + currentTime + " " + message + "
"); $('#console').prepend(element); }script>html>
准备工作已经完成,现在我们可以尝试将 socket.io 运行起来。打开 CMD,输入 node “app.js 所在位置\app.js”。我的桌面位置是 C:\Users\minghui\Desktop\。所以我输入的是 node C:\Users\minghui\Desktop\socketIOdemo\js\app.js。
用浏览器打开我们编写的 chat.html。
好了,这个 socket.IO 小程序已经顺利的运行了。
2. 在 java web 程序中使用 socket.io
在 java 端我们使用的是 netty-socketio,是 Socket.IO 在 JAVA 端移植版本。我们可以到这个地址去下载:
https://www.versioneye.com/java/com.corundumstudio.socketio:netty-socketio/1.7.7
我下载的是 netty-socketio-1.7.7.jar。
最后来一张所有 lib 的图:
一定要全部下载并引用,现在我们创建一个 web 项目。
只需要勾选 web 即可,项目名我写的是 socketiodemo,然后 finish。附一张完成的项目图:
现在我们将代码贴上:
ChatBean
App
SocketIOChatListener