使用Socket.IO可以避免webSocket产生的问题;
传输:
- Socket.IO中消息的传递是基于传输的,而非全部依靠WebSocket;
- 它总会尝试选择对用户来说速度最快、对服务器性能来说最好的方法来建立连接;
- 要是条件达不到,那么首先会保证连接正常;
断开VS关闭: //对超时的支持
- Socket.IO监听的是connect事件而不是open事件;是discounnect事件而不是close事件;
- 若客户端停止传输数据,但一定时间内又没有正常关闭连接,Socket.IO就会认为它是断开连接了;
- 当连接丢失时,Socket.IO默认会自动重连;
事件://典型的web通信方式是通过HTTP收发文档的;但实际中都是基于事件传输的;
- Socket.IO允许像WebSocket那样传输简单文本信息;
- 此外,还支持通过emit和listen事件进行JSON数据收发;
命名空间://Socket.IO允许在单个连接中利用命名空间来将消息彼此区分;
有些时候程序需要进行逻辑拆分,但考虑到实际的性能问题,不希望依赖同时打开过多连接;而Socket。IO会对同样的资源进行频道分割,并将数据传输给对应的回调函数,一般情况下会使用一个传输通道;
//server io.sockets.on('connection'); io.of('/some/namespace').on('connection); io.of('/some/other/namespace').on('connection'); //client var socket = io.connect(); var socket1 = io.connect('/some/namespace'); var socke2 = io.connect('/some/other/namespace');
构建一个聊天系统:
- package.json:
{ "name": "chat.io", "version": "0.0.1", "dependencies": { "express": "2.5.1", "socket.io": "0.9.2" } }
- server.js:
var express = require('express'); var sio = require('socket.io'); var app = express.createServer(express.bodyParser(), express.static('public')); app.listen(3000); //将socket.io绑定到app上; var io = sio.listen(app); //设置连接监听器; io.sockets.on('connection', function(socket) { socket.on('join', function(name) { socket.nickname = name; //如果使用socket.emit则只是将消息返回客户端;broadcastt是个消息标志,表示广播给所有用户 socket.broadcast.emit('announcement', name + ' joined the chat.'); }); socket.on('text', function(msg,callback) { socket.broadcast.emit('text', socket.nickname, msg); callback('title'); //调用'text': socket.emit传来的回调方法; }); });
- public/index.html
<div id='chat'> <ul id='messages'></ul> <form id='form'> <input id='input' type='text'/> <button>Send</button> </form> </div> //当Socket.IO绑定到http.server之后,所有以/socket.io开始的url都会被拦截; <script type="text/javascript" src='/socket.io/socket.io.js'></script> <script type="text/javascript" src='/chat.js'></script>
- chat.js
//Socket.IO自带了其浏览器端运行的代码,直接使用; window.onload = function() { //所有Socket.IO客户端代码暴露出来的方法和类都在io命名空间中; var socket = io.connect(); socket.on("connect", function() { //通过join事件发送昵称; socket.emit('join', prompt('What is your nickname?')); //显示聊天窗口 document.getElementById('chat').style.display = 'block'; socket.on('announcement', function(msg) { var li = document.createElement('li'); li.className = 'announcement'; li.innerHTML = msg; document.getElementById('messages').appendChild(li); }); }); function addMessage (from, text) { var li = document.createElement('li'); li.className = 'message'; li.innerHTML = '<b>' + from + '</b>: ' + text; document.getElementById('messages').appendChild(li); return li; } var input = document.getElementById('input'); document.getElementById('form').onsubmit = function() { //这里是在自己的广播提交之后立即将信息打印出来,并没有服务器确认是否接受成功; var li = addMessage('me', input.value); socket.emit('text', input.value, function(data) { //这个回调函数用于确认消息接受成功; li.className = 'confirmed'; li.title = date; }); //重置输入框 input.value = ''; input.focus(); return false; } //用于打印其他用户广播; socket.on('text', addMessage); }