首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Socket.IO 入门

「文末高能」

编辑 哈比

1. Socket.IO 原理

node.js 提供了高效的服务端运行环境,但是由于浏览器端对 HTML5 的支持不一,为了兼容所有浏览器,提供卓越的实时的用户体验,并且为程序员提供客户端与服务端一致的编程体验,于是 socket.io 诞生。

Socket.io 将 Websocket 和轮询 (Polling)机制以及其它的实时通信方式封装成了通用的接口,并且在服务端实现了这些实时机制的相应代码。

也就是说,Websocket 仅仅是 Socket.io 实现实时通信的一个子集。那么,Socket.io 都实现了 Polling 中的那些通信机制呢?

WebSocketAdobe Flash SocketAJAX long pollingAJAX multipart streamingForever IframeJSONP 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 代码如下:

varapp =require('http').createServer(handler), io =require('socket.io').listen(app), fs =require('fs')app.listen(3000);// 服务器监听的端口号 3000functionhandler(req, res)res.writeHead(200);res.end(data);});}/* 以上是标准写法,无特殊情况不用修改 **//* 下面是开启 socketio 链接监听 **/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.emit('chatevent', { userName: data.userName,message:data.message });/* 给除了自己以外的客户端广播消息 *///socket.broadcast.emit('chatevent', { userName: data.userName,message:data.message });});socket.on('disconnect',function(){console.log(' 客户端断开连接 ');});});console.log("success listening port:3000");

Socketio chatbody{padding:20px;}#console{height:400px;overflow:auto;}.username-msg{color:orange;}.connect-msg{color:green;}.disconnect-msg{color:red;}.send-msg{color:#888}Netty-socketio chat demo发送Date.prototype.Format =function(fmt){//author: meizzvaro = {"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(varkino)if(newRegExp("("+ k +")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length ==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length)));returnfmt; }varsocket = 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(' 客户端已断开连接 ! '); });functionsendDisconnect(){ socket.disconnect(); }functionsendReconnect(){ socket.reconnect(); }/* 点击发送按钮 */functionsendMessage(){varuserName = $("#name").val();varmessage = $('#msg').val();varchatDate =newDate();$('#msg').val('');socket.emit('message', {userName : userName,message : message}); }functionoutput(message){varcurrentTime =""+newDate().Format("yyyy-MM-dd HH:mm:ss") +"";varelement = $("

"+ currentTime +" "+ message +"

");$('#console').prepend(element);}

准备工作已经完成,现在我们可以尝试将 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

SysAuthorizationListener

index.jsp

项目建好了,现在我们可以跑起来试一下。首先我们启动 App.java 里面的 main 方法。

启动成功,现在我们再启动 web 项目,起来之后,我们进入主页。

由于是一个简单的项目,并没有使用数据库,所以也就没有做登陆了,以后整合进项目之后,可以直接用系统的用户名来代替。最后我们来聊天试试效果。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171218B0299D00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券