socket.io.js是不是已经不维护了

java里tcp中socket的io流到底要不要关闭,请说下原因。_百度知道7950人阅读
谈到socket.io,就不能不提一下websocket,websocket是html5的新特性之一,多少web开发者为之兴奋,websocket可以使web程序客户端和服务端之间保持长连接,可以实现实时通讯,而且API简单易用,但是由于浏览器的支持不同,又是一个头疼的事情。后来,socket.io出现了,在某种程度上,socket.io就是websocket,其实socket.io与websocket不是一回事,而且websocket可以说是socket.io的一个子集,socket.io的底层实现其实有5种方式,websocket只是其中一种,只不过在默认的情况下,我们建立的socket.io连接,底层也是调用websocket的实例。当我们io.connect()建立一个socket连接的时候,返回的是namespace实例,namespace实例中有个socket实例,当新建一个连接,或者发送一条消息的时候,namespace-&socket-&transport-&websocket(xhrpolling...),其实发送一条消息真正的发送者还是底层的websocket或是xhrpolling或其他的几种,而socket.io只是一个组织者,当我们需要建立连接的时候,它自己会在其内部挑选一种连接方式,然后实现连接。具体的socket.io内部实现还需要进一步学习源码。
本文的水平还只是在socket.io的实践上,其内核具体实现还需要不断探索。接下来就分享一些最近在socket.io开发中的一些经验,主要是客户端的,服务端的了解也不深,但是相信也是大同小异。
首先就是简单介绍socket.io的用法:
socket = io.connect(&http://& + config.serverip + &:& + config.serverport, { 'reconnect': true });
socket.on('connect', function(data) {
console.log(&Connected to Server&);
global.reconnectFailCount = 0;
socket.on('connect_failed', function(data) {
console.log(&connect_failed to Server&);
socket.on('error', function(data) {
console.log(&error&);
alert(&连接服务器失败!!!&);
socket.on('reconnecting', function (data) {
console.log(&reconnecting&);
global.reconnectFailCount++;
if (global.reconnectFailCount &= 6) {
alert(&连接服务器失败,请检查您当前的网络&);
socket.on('reconnect', function (data) {
console.log(&reconnect&);
global.reconnectFailCount--;
socket.on('disconnect', function (data) {
console.log(&disconnect&);
如上所示,我们就创建了一个socket连接,这里需要强调一点,默认情况下,无论我们创建了多少次socket连接,指向都是同一个socket实例,除非我们在connect()的第二个参数中指定&force new socket&强制建立一个新的连接。socket实例监听了其connect,connect_failed等等事件,不要小看这些事件,其实都很有用,弄明白他们,socket.io基本无大问题,我们一一来分析一下。刚刚创建一个socket的时候,其实这只是一个空的socket,而且并未分配一个id,只有当与服务器连接成功后,才会生成一个id,因此我们在connect中才能得到获取socket的id,有些时候,socket的id是很有用的,有时会用于存储对应socket的用户信息。socket连接成功后,服务端与客户端会定时发送心跳包,若某一方长时间未回应,默认连接断开,当我们的网络不稳定或者有其他影响连接的因素存在的时候,则会与服务器断开连接,断开时会触发disconnect监听,若我们没有声明reconnect的时候,断开就不再与服务器重新连接,若我们在创建的时候如上声明了reconnect:true,那么断开后客户端还是会尝试新的连接,就会触发reconnecting监听,若连接未成功,会继续尝试多次连接,若连接成功,则会触发reconnect监听,此时,原有的socket连接已经不再,内部会创建一个新的连接,并且socket得到一个新的id,最后会再一次触发connect监听。
虽然这里暂时并没有深入socket.io内核实现,但是明白了这些,利用socket.io实现即时通讯就完全没有问题,而且连接比较稳定,即使中间会有重连小插曲,处理得好,完全不会有问题。以后再慢慢深入讨论。
本人对socket.io的认识尚肤浅,请尽管拍砖,好让我查漏补缺。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:269261次
积分:1986
积分:1986
排名:第14621名
原创:28篇
转载:14篇
评论:104条
(2)(3)(2)(1)(2)(2)(4)(3)(3)(9)(9)(2)
xuesongtanSocket.io:有点意思 - 推酷
Socket.io:有点意思
下面页面就是使用
制作的口袋妖怪游戏(默认小屏下已隐藏,请切换到大分辨率查看)。左边是游戏画面,右边是按键表和聊天室。画面达到红蓝版本的水平了。
前导 ——WebSocket的介绍 传统的Web应用采用的是客户端发出请求、服务器端响应的工作方式。在这种情景下,浏览器作为Web应用的前端,自身的处理功能是十分有限的。这种方法不能满足某些应用的实时需求(服务器需要主动更新浏览器端的数据)。不同于服务器端等待HTTP请求,这需要服务器端主动发送数据以给客户端更新。解决方案有两类:一类是基于HTTP的Comet推送技术,另一类是基于套接口(Socket)传送信息实现消息传输。而目前使用Comet主要有两种方式,轮询和iframe流。
轮询 polling浏览器周期性的发出请求,如果服务器没有新数据需要发送就返回以空响应。这种方法问题很大:首先,大量无意义的请求造成网络压力;其次,请求周期的限制不能及时地获得最新数据。这种方法很快就被淘汰。
长轮询 long polling长轮询是在打开一条连接以后保持连接,等待服务器推送来数据再关闭连接。然后浏览器再发出新的请求,这能更好地管理请求数量,也能及时地更新数据。AJAX调用XMLHttpRequest对象发出HTTP请求,JS响应处理函数根据服务器返回的数据更新HTML页面的展示。这个方法一定程度上消除了简单轮询的弊端,但服务器压力也是很大。
iframe流 iframe streamingiframe流方式是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间建立一条长链接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。&iframe是很早就存在的一种 HTML 标记,通过在 HTML 页面里嵌入一个隐蔵帧,然后将这个隐蔵帧的 SRC属性设为对一个长连接的请求,服务器端就能源源不断地往客户端输入数据。”其不足为:进度条会显示一直,反应在页面上就是浏览器标签页的图标会不停地转动。(当然这也是有解决方法的)
另一类方法则是基于WebSocketHTML5提供的Websocket不同于上面这些在老的HTML已有框架内的方法,而是在单个TCP连接上进行全双工通讯的协议。目前主流浏览器都已支持。1. 初始化过程不同于早期JAVA使用在浏览器安装插件的方法——-Java Applet 套接口:这种方法不足在于Java Applet再收到服务器返回的消息后,无法通过Javascript去更新HTML页面的内容。而是通过HTTP建立连接(HTTP handshake)。2. 开始通讯一旦初始连接建立,浏览器和服务器就打开了一个TCP socket的频道。在这个频道内就能进行双向的数据通信。 然而Websocket依然有一些问题。比如浏览器兼容性问题(随着浏览器的发展,肯定是越来越小的),以及网络中间物(代理服务、防火墙)问题不支持WebSocket,这时Socket.io的出现就是为了完善WebSocket。
Socket.IO Guillermo Rauch在2010年开发第一版时,目的很明确地指向Node.js实时应用。在几次版本更新后,重新定义和封装核心功能而分化出一个基础模块 Engine.io——力求建立更稳定的工具。Engine.IO有着更稳定的连接质量。使得Socket.IO在先打开一个长轮询,再在将连接推至WebSocket频道继续通信。在使用Node的http模块创建服务器同时还要Express应用,因为这个服务器对象需要同时充当Express服务和Socket.io服务。(如下) var app = require('express')(); //Express服务
var server = require('http').Server(app); //原生Http服务
var io = require('socket.io')(server); //Socket.io服务
io.on('connection', function(socket){
/* 具体操作 */
server.listen(3000);
当客户端需要连接服务器时,它需要先建立一个握手。io.处理连接事件,socket 处理断开连接事件。在上面代码里,这套握手机制是完全自动的,我们可以通过也可以io.use()方法来设置这一过程。客户端使用js调用socket.io的Client API即可。 &script src=&/lib/socket.io/socket.io.js&&&/script&
var socket = io();
socket.on('connect', function() {
/* 具体操作 */
Socket.IO还要一些系统事件,包括了连接、重连、关闭的事件。我们也可以自定义事件,以及监听方法。 socket.on('customEvent', function(customEventData) {
/* 具体操作 */
相应地,在对的时间和地方的调用.emit('customEvent', customEventData); 触发事件就行了。不过,事件是无法在客户端之间发送的。同一个服务器可以使用namespaces创造不同的Socket连接。Socket.IO使用of()来指定不同的命名空间。 io.of('/someNamespace').on('connection', function(socket){
socket.on('customEvent', function(customEventData) {
/* 具体操作 */
io.of('/someOtherNamespace').on('connection', function(socket){
socket.on('customEvent', function(customEventData) {
/* 具体操作 */
服务器端则通过在定义Socket对象时传递namespace参数。 &script&
var someSocket = io('/someNamespace');
someSocket.on('customEvent', function(customEventData) {
/* 具体操作 */
var someOtherSocket = io('/someOtherNamespace');
someOtherSocket.on('customEvent', function(customEventData) {
/* 具体操作 */
在每一个namespace中又可以使用room来进一步划分,不过sockets是使用join()、leave()来调用。 //服务器端
io.on('event', function(eventData){
//监听join事件
socket.on('join', function(roomData){
socket.join(roomData.roomName);
//监听leave事件
socket.on('leave', function(roomData){
socket.leave(roomData.roomName);
//浏览器端
io.on('connection', function(socket){
//在此room下触发事件
io. in('someRoom') .emit('customEvent', customEventData);
书中的例子来实际操作一下。
配置Socket.io服务器首先安装安装Socket.IO、connect-mongo、cookie-parser依赖我们先将依赖报引入,然后定义服务器对象。
var http = require('http');
var socketio = require('socket.io');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
配置Socket.io Session为了是Socket.io seesion 和Express session一起工作,我们必须让他们信息共享。Express Session 默认是存储在内存,我们需要把它存在mongoDB以便Socket.io能获取。使用connect-mongo来控制session信息的存储,以及使用以前用到过的cookie-parse来解析session cookie信息。先来修改express.js文件以便connect-mongo能够正常使用。
var mongoStore = new MongoStore({
db: db.connection.db //通过server.js传递参数db到express的配置中
app.use(session({
saveUninitialized: true,
resave: true,
secret: config.sessionSecret,
store: mongoStore
这样Session就存到数据库中来,新建配置文件socketio.js来配置socketio var config = require('./config'),
cookieParser = require('cookie-parser'),
passport = require('passport');
* @description
* @param {HTTP object} server 带socket服务的http服务
* @param {Socket.io Object} io 监听server的Socket服务
* @param {MongoStore Object} mongoStore mongoDB的存储
module.exports = function(server, io, mongoStore){
io.use(function(socket, next){
//解析请求socket.request
cookieParser(config.sessionSecret)(socket.request, {}, function(err){
//获得sessionId
var sessionId = socket.request.signedCookies['connect.sid'];
//获得数据库中的session数据
mongoStore.get(sessionId, function(err, session){
socket.request.session =
//填充 socket.request.user对象
passport.initialize()(socket.request, {}, function(){
passport.session()(socket.request, {}, function(){
if(socket.request.user){
next(null, true);
next(new Error('User is not authenticated'), false);
io.on('connection', function(socket){
console.log('a socket is connected');
require('../app/controllers/chat.server.controller')(io, socket);
cookieParser首先解析Express的Session,然后读取sessionId获得数据库中的session数据,填充到user对象中。如果通过passport来验证用户数据是非法的,则跳出Socket.IO的设置,并发出错误提示。接下来只需要建立Socket.IO的后端控制器即可完成后端的开发。
配置chat控制器chat功能的控制器统一监听和触发Socket.IO事件来进行数据通信。通过事件处理的回调函数来控制数据格式的建立和分发。
module.exports = function(io, socket){
//触发chatMessage事件,提示用户已连接
io.emit('chatMessage', {
type: 'status',
text: 'connected',
created: Date.now(),
username: socket.request.user.username
//监听chatMessage事件,获得用户的消息
socket.on('chatMessage', function(message){
message.type = 'message';
message.created = Date.now();
messsage.username = socket.request.user.
//触发事件并发送数据。
io.emit('chatMessage', message);
//监听断开连接事件
socket.on('disconnect', function(message){
//触发事件并发送数据。
io.emit('chatMessage', {
type: 'status',
text: 'disconnected',
created: Date.now(),
username: socket.request.user.username
确定监听事件规则后,将控制器载入到Socket.IO的连接事件处理函数中即可。 io.on('connection', function(socket){
console.log('a socket is connected');
require('../app/controllers/chat.server.controller')(io, socket);
Angular前端设计我们先通过建立ng-resource来封装Socket.IO的方法,再中前端的控制器中调用。service是懒加载,即只有在请求时才加载。这可以阻止未验证用户调用到service的方法来获得数据,将emit()、on()、removeListenter()一套方法封装成的更相容的服务方法,减少代码的重写。然而ng的数据绑定只有在框架内执行的方法才能实时改变,也就是说第三方事件导致的数据模型的改变是未知的。那么,我们在socket中任何事件被触发时,处理函数对数据的修改可能不会及时地绑定到$scope数据模型上。(这都是抄来的)这里使用$timeout来强制完成数据的绑定。
angular.module('chat').service('Socket', ['Authentication', '$location', '$timeout', function(Authentication, $location, $timeout){
//首先确认用户
if(Authentication.user){
this.socket = io();
$location.path('/');
//通用监听方法
this.on = function(eventName, callback){
if(this.socket){
this.socket.on(eventName, function(data){
$timeout(function(){
callback(data);
//通用触发方法
this.emit = function(eventName, data){
if(this.socket){
this.socket.emit(eventName, data);
//通用删除监听器的方法
this.removeListener = function(eventName){
if(this.socket){
this.socket.removeListener(eventName);
接着在前端控制器中调用这些方法来处理后端触发的事件和触发后端能处理的事件。 //监听后端发送的chatMessage事件
Socket.on('chatMessage', function(message){
$scope.messages.push(message);
//监听后端发送的chatMessage事件
$scope.sendMessage = function(){
var message = {
text: this.messageText
//监听后端发送的chatMessage事件
Socket.emit('chatMessage', message);
//及时清空ng-model
this.messageText = '';
//监听$destroy,当controller实例被摧毁删除 监听器
$scope.$on('$destroy', function(){
Socket.removeListener('chatMessage');
将ng引入到对应的视图模板,测试一下即可。
以上就是Socket.IO的上手实战。先了解Socket.IO的工作机制,再将整个数据通信的流程走了一遍,在实践上将Socket.IO与Express、Passport整合到一起完成了Web聊天室的功能,也见识到了Node.JS的小组件大组合的哲学。
References:
已发表评论数()
请填写推刊名
描述不能大于100个字符!
权限设置: 公开
仅自己可见
正文不准确
标题不准确
排版有问题
主题不准确
没有分页内容
图片无法显示
视频无法显示
与原文不一致socket.io是否可以跨socket轉發消息? - CNode技术社区
这家伙很懒,什么个性签名都没有留下。
例如兩個客戶端連接了socket.io服務器,一個的socket id是,另一個是。我能否實現這樣的功能,當接受到’event1’消息時,向發’event2’消息?簡而言之就是實現客戶端與客戶端的通信轉發。
没试过… 这个发送 special client 行不?
奇怪. change log 里面提到 .client() 方法但首页 README 里没写…
具體如何?
先把socket存起来,然后在event1的handle里emit就可以了
var sockets = {};
io.sockets.on('connection', function (socket) {
var id = Math.random().toString(32).substr(2);
socket.id =
sockets[id] =
socket.on('event1', function (msg) {
sockets[''].emit('event2', msg);
這樣開多線程後就不行了
用redis實現了一個pub/sub通信,已經解決。
CNode 社区为国内最专业的 Node.js 开源技术社区,致力于 Node.js 的技术研究。
服务器赞助商为
,存储赞助商为
,由提供应用性能服务。
新手搭建 Node.js 服务器,推荐使用无需备案的socket.io涓巒ode.js鐨勫伐浣滀笉姝e父-node.js,socket.io-CodeGo.net
socket.io涓巒ode.js鐨勫伐浣滀笉姝e父
鎴戝垱寤轰簡绠鍗曠殑鑱婂ぉ鐨刵ode.js +socket.io銆傚綋鎴戝皾璇曡繍琛屽畠锛屽畠涓嶄細鎸夐鏈熻繍琛岋細瀹冩槸涓嶆柇鍙戦佹潵鑷鎴风绔殑璇锋眰銆傛垜宸茬粡閰嶇疆浼犺緭鏂瑰紡璁剧疆锛['jsonp-polling', 'xhr-polling']鍦ㄨ繖涓や釜锛堝鎴风绔/鏈嶅姟鍣級鐨勪竴闈傛垜璇曠潃璁剧疆['close timeout': 10]锛屼絾杩欏苟娌℃湁鏀瑰彉浠讳綍涓滆タ銆傛垜涓嶆槑鐧借繖閲屽彂鐢熶簡浠涔堛
鎴戣寰楁垜鍦ㄦ柇寮鐨勮繛鎺ワ紝鎴戝湪鏃ュ織鏂囦欢涓湅鍒帮紙鍦ㄦ湯灏撅級銆
涓嬮潰鏄垜鐨勪唬鐮侊細
鏈嶅姟鍣ㄧ锛歛pp.js
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
var sio = require('socket.io');
var io = sio.listen(app)
io.configure(function () {
io.enable('browser client minification');
io.enable('browser client etag');
io.enable('browser client gzip');
io.set('log level', 3);
io.on('connection', function (client) {
client.on('message', function (msg) {
socket.broadcast(msg);
client.on('disconnect', function () {
瀹㈡埛绔锛
〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜
&!DOCTYPE html&
&script src=" CodeGo.net
&script src=" CodeGo.net
$(document).ready(function () {
var socket = new io.Socket("localhost", {port: 8080});
socket.on('connect', function () {
socket.send('A client connected.');
socket.on('message', function (message) {
$('div#messages').append($('&p&'), message);
socket.on('disconnect', function () {
console.log('disconnected');
socket.connect();
$('input').keydown(function (event) {
if(event.keyCode === 13) {
socket.send($('input').val());
$('input').val('');
&input type="text" style="width: 300" /&
&div id="messages" style="border:solid 1px #000;"&&&/div&
浠ヤ笅鏄棩蹇楁枃浠讹細
debug: client authorized
info: handshake authorized U1Y79P8WLaMz_UWoiKTc
debug: setting request GET /socket.io/1/xhr-polling/U1Y79P8WLaMz_UWoiKTc?t=8
debug: setting poll timeout
debug: client authorized for
debug: clearing poll timeout
debug: xhr-polling writing 1::
debug: set close timeout for client U1Y79P8WLaMz_UWoiKTc
debug: setting request GET /socket.io/1/xhr-polling/U1Y79P8WLaMz_UWoiKTc?t=4
debug: setting poll timeout
debug: discarding transport
debug: cleared close timeout for client U1Y79P8WLaMz_UWoiKTc
debug: setting request GET /socket.io/1/xhr-polling/ufw4UqC2pCvWqqB5iKOQ?t=8
debug: setting poll timeout
debug: clearing poll timeout
debug: xhr-polling writing 7:::1+0
debug: set close timeout for client ufw4UqC2pCvWqqB5iKOQ
warn: client not handshaken client should reconnect
info: transport end (error)
debug: cleared close timeout for client ufw4UqC2pCvWqqB5iKOQ
debug: discarding transport
debug: client authorized
info: handshake authorized Uslh5g1YKNE8rCJDiKTd
debug: client authorized
info: handshake authorized -XHkL7Zk9KzA7WEFiKTe
debug: client authorized
info: handshake authorized _OOsM2nZOVgS93R-iKTf
debug: client authorized
info: handshake authorized IZ0vUej2iX_-TRSJiKTg
debug: setting request GET /socket.io/1/xhr-polling/IZ0vUej2iX_-TRSJiKTg?t=7
debug: setting poll timeout
debug: client authorized for
debug: clearing poll timeout
debug: xhr-polling writing 1::
debug: set close timeout for client IZ0vUej2iX_-TRSJiKTg
浠讳綍浜洪兘鍙互鎻愬嚭杩欎釜闂瀹為檯涓婂浣曡皟璇曡繖涓棶棰橈紝鎴栬呮槸浠涔堬紵
鏈枃鍦板潃 锛欳odeGo.net/494031/
-------------------------------------------------------------------------------------------------------------------------
1. io.on('connection', function (client) {
搴io.sockets.on(...client.on('message', function (msg) {
socket.broadcast(msg);
搴client.broadcast(msg);锛socket娌℃湁瀹氫箟浠讳綍鍦版柟锛
鎮ㄥ彲浠ラ厤缃畇ocket.io璁剧疆鎸夋偍鐨
鎴戜篃閬囧埌浜嗚繖涓棶棰橈紝骞跺彂鐜帮紝娣诲姞涓嬮潰涓琛岃В鍐抽棶棰
io.set('transports',['xhr-polling']);
鏈枃鏍囬 锛歴ocket.io涓巒ode.js鐨勫伐浣滀笉姝e父
鏈枃鍦板潃 锛欳odeGo.net/494031/
Copyright 漏 2014 CodeGo.net

我要回帖

更多关于 nodejs socket.io 的文章

 

随机推荐