前面两篇文章使用了Ajax long polling和WebSocket两种经常使用的Web实时通讯方式构建了简单的聊天程序。css
可是,因为浏览器的兼容问题,不是全部的环境均可以使用WebSocket这种比较好的方式。也就是说,根据浏览器或者环境的不一样,客户端和服务端可能须要使用不一样的通讯方式。html
为了解决上面的问题,Socket.IO就出现了。jquery
Socket.IO是一个基于Nodejs的,用于实时通讯的一个软件包(包括client端和server端),Socket.IO彻底由JavaScript实现。json
Socket.IO设计的目标是支持任何的浏览器,任何设备。在接口方面,Socket.IO统一了通讯的API,在内部实现上支持WebSocket,AJAX long-polling, AJAX multipart streaming, Forever Iframe等方式。也就是说,Socket.IO会根据环境来选择适合的通讯方式。数组
在Socket.IO中,还有namespace和room的概念,能够方便的对socket进行分组,方便的实现一些例如聊天室的应用。浏览器
关于更多Socket.IO相关的内容,请参考该连接。服务器
好吧,又是聊天程序,此次是Socket.IO版本。app
在实现方面,客户端直接使用Socket.IO 的client,服务器端使用Nodejs。socket
客户端首先建立一个socket对象,这个socket对象会监听"new_message"和"user_status"事件。工具
var socket; function initSocket(){ socket = io("http://" + location.host); socket.emit("add_client", $("#clientNameSpan").text()); socket.on("new_message", function(data){ console.log(data); data = eval("(" + data + ")"); if (data.sender == $("#clientNameSpan").text()){ $("#inbox").append("<div class='chatItemS'><span class='msg mSend'><span class='sender'>"+data.sender+": </span>"+data.msg+"</span></div>"); } else { $("#inbox").append("<div class='chatItemR'><span class='msg mRecv'><span class='sender'>"+data.sender+": </span>"+data.msg+"</span></div>"); } $("#inbox").scrollTop($("#inbox")[0].scrollHeight); }); socket.on("user_status", function(data){ $("#clientCount").text("Online User: "+data.length); $("#clients").children().remove(); for(var i = 0; i<data.length; i++){ $("#clients").append("<span id='client'>"+data[i]["clientName"]+"</span>") } }) }
对于服务端,首先是一些静态文件、页面的处理。
// get the static files app.get("/", function(req, res){ res.sendFile(__dirname + "/index.html"); }); app.get("/static/jquery-1.11.3.js", function(req, res){ res.sendFile(__dirname + "/static/jquery-1.11.3.js"); }); app.get("/static/json2.js", function(req, res){ res.sendFile(__dirname + "/static/json2.js"); }); app.get("/static/style.css", function(req, res){ res.sendFile(__dirname + "/static/style.css"); });
另外,服务端主要的功能就是接收消息,而后广播消息。
服务端会根据socket id和用户名记录全部的用户,并存放在一个数组中。每当有用户加入或者用户退出,服务端就经过"user_status"事件将用户数组发送给客户端,这样客户端就能展现当前在先用户数。
// save all the client {"sid": socket.id, "clientName": client} var clients = [] io.on("connection", function(socket){ socket.on("add_client", function(client){ console.log(client+" jion the chat"); var clientObj = {}; clientObj["sid"] = socket.id; clientObj["clientName"] = client; clients.push(clientObj); io.emit("user_status", clients) }); socket.on("new_message", function(msg){ console.log("Server got message: "+msg); console.log("Send message using: "+socket.conn.transport.name); io.emit("new_message", msg); }); socket.on("disconnect", function(){ for(var i = 0; i<clients.length; i++){ if(clients[i]["sid"] == socket.id){ console.log(clients[i]["clientName"]+" leave the chat"); clients.splice(i, 1); break; } } io.emit("user_status", clients); }); });
首先是一个login页面,在服务端会将用户名跟socket id绑定,用来进行简单的用户统计。
Console端打印了服务器收到的消息,以及用户的join/leave状况。
当用户状态改变后,页面会收到"user_status"事件,而后更新用户状态栏。
前面提到了Socket.IO的优点就是统一了接口,对用户屏蔽了底层,同时可以支持不一样的设备,选择最优的通讯方式。
下面就对Socket.IO的兼容性进行一些简单的测试,主要看看IE7-10。
首先,注意服务端的下面一段代码,用于显示当前传递消息的通讯方式:
console.log("Send message using: "+socket.conn.transport.name);
我本机安装的是IE10,经过服务端console能够看到,在IE10中Socket.IO会选择"WebSocket"为最终通讯方式。
打开IE,经过F12进入下面页面,而后设置为IE9。
经过测试能够看到,Socket.IO在IE9中能够正常工做,因为IE9不支持“WebSocket”,因此Socket.IO最终选择了"Polling"为最终通讯方式。
经过上面的设置切换到IE8模式,因为IE8不支持“WebSocket”,因此Socket.IO就会将通讯方式切换到了“Polling”。
经过一样的步骤测试,Socket.IO在IE7中使用polling方式正常工做。
IE7中惟一遇到的问题是“JSON.stringify”方法不支持,因此经过下面方式对IE7进行了hack:
<!--[if IE 7]> <script src="/static/json2.js"></script> <![endif]-->
从例子中能够看到,使用了Socket.IO后,咱们只须要了解Socket.IO提供的API,而不须要关心使用哪一种通讯方式,使用起来简单、方便。
文中对Socket.IO在IE上的兼容性作了一些简单的测试,结果仍是很满意的,对于不支持WebSocket的环境,Socket.IO自动切换到了polling方式,用户不用去关心环境的差别了。
Socket.IO做为一个跨环境,多种链接方式自动切换的工具,进一步简化了Web实时通讯方面应用的开发。
Ps:经过此处能够下载例子的源码。