Socket.IO Server API

原文链接:https://github.com/socketio/socket.io/blob/master/docs/API.md

仅用于学习参考,欢迎指出翻译错误Q^Q

Server

require("socket.io")暴露的接口。

new Server(httpServer[, options])

  • httpServer(http.Server)服务器绑定的http协议
  • options(对象)
  • path(字符串):捕获的路径名称(/socket.io)
  • serveClient(布尔值):是否向提供客户端文件(true)
  • adapter(适配器):使用适配器。默认为socket.io自带的基于内存的Adapter实例。详情见socket.io-adapter
  • origins(字符串):允许的origins(*)
  • allowRequest(函数):一个接收被给予握手协议或是升级请求作为第一参数的函数,它可以决定是否继续。第二个参数是一个回调函数,用于处理决定是否继续的信息:fn(err, success),这里的success是一个布尔值,false意味着请求被拒绝了,err是错误代码。
  • parser(解析器):使用解析器。默认为socket.io自带的Parser实例。详情见socket.io-parser

使用或不适用new的不同写法:

var io = require("socket.io")();
//or
var Server = require("socket.io");
var io = new Server();

传给socket.io的选项总是会传递给已创建的engine.io服务器。详情参考engine.io options

除此之外的一些选项:

  • pingTimeout(数字):在不考虑回应的包时连接关闭的时长毫秒数(60000)。
  • pingInterval(数字):发送ping间隔时间毫秒数(25000)。

以上两个参数会影响客户端知道服务器端不再可获得的延迟状况。例如:如果底层的TCP连接因为网络原因没有正常关闭,那么客户端得到disconnect事件可能需要等待的时间为pingTimeout + pingInterval毫秒。

  • transports(数组):transports允许和(['polling', 'websocket'])有连接。

**注意:**次序是很重要的。默认情况下:首先建立的是一个长轮询连接,然后才可能升级为WebSocket。用['websocket']意味着即使WebSocket连接未能成功打开也不能回退。

new Server(port[, options])

  • port(数字)监听的端口(一个新的http.Server会被创建)
  • options(对象)

这里了解可选参数

new Server(options)

  • options(对象)

这里了解可选参数

server.sockets

  • (命名空间)

默认的命名空间(/)。

server.serveClient([value])

  • value(布尔值)
  • Returns Server|布尔值

如果valuetrue,那么连接的服务器(见Server#attach)则可以传输客户端文件。默认为true。在attach被调用后这个方法会失去效果。如果没有传参这个方法将返回当前的值。

// pass a server and the `serverClient` option
var io = require('socket.io')(http, {serveClient: false});

// or pass no server and then you can call the method
var io = require('socket.io')();
io.serveClient(false);
io.attach(http);

server.path([value])

  • value(字符串)
  • ReturnsServer|字符串

设置engine.io和静态文件被提供的路径。默认为/socket.io。如果没有传递参数会返回当前值。

server.adapter([value])

  • value(适配器)
  • Returns Server|字符串

设置适配器的值。默认为socket.io自带的基于内存的Adapter实例。见socket.io-adapter。如果没有传参该方法将返回当前值。

server.origins([value])

  • value(字符串)
  • ReturnsServer|字符串

设置允许的‘origins’值。默认情况下任何‘origins’都是允许的。如果没有传参该方法返回当前值。

server.origins(fn)

  • fn(函数)
  • ReturnsServer

这里的函数‘fn’带有两个参数origin: Stringcallback(error, success)success是一个指示‘origin’是否被允许的布尔值。

潜在弊端

  • 在某些情况下,你不能确保origin的值不为*
  • 由于每次请求都会导致这个函数的执行,所有建议让它尽快被调用执行
  • 如果socket.io是和express一起使用的,CORS头只会被来自socket.io的请求所影响。Express可以使用cors

server.attach(httpServer[, options])

  • httpServer(http.server)要连接的http服务器
  • options(对象)

httpServer上用提供的options(可选的)把Server连接到一个engine.io的实例上。

server.attach(port[, options])

  • port(数字)要监听的端口号
  • options(对象)

在一个新的http.server上用提供的options(可选的)把Server连接到一个engine.io的实例上。

server.listen(httpServer[, options])

和server.attach(httpServer[, options])相同

server.listen(port[, options])

和server.attach(port[, options])相同

server.bind(engine)

  • engine(engine.Server)
  • ReturnsServer

高级用法。把服务器绑到特定的engine.io Server(或者兼容的API)实例。

server.onconnection(socket)

  • socket(engine.Socket)
  • ReturnsServer

高级用法。从接入的engine.io(或兼容的API)Socket创建一个新的socket.io客户端。

server.of(nsp)

  • nsp(字符串)
  • Returns命名空间

利用nsp路径名标识符来初始化和检索命名空间。如果命名空间已经被初始化了则立即返回该命名空间。

server.close([callback])

  • callback(函数)

关闭socket.io服务器。callback参数是可选的,它会在所有连接关闭后调用。

var Server = require('socket.io');
var PORT = 3030;
var server = require('http').Server();

var io = Server(PORT);

io.close(); // close current server

server.listen(PORT); // PORT is free to use

io = Server(server);

server.engine.generated

重写默认的方法来创建自定义的socket id。

当把一个node请求(http.IncomingMessage)作为第一个参数时函数会被调用。

io.engine.generateId = function (req) {
 return "custom: id:" + custom_id++; //custom id must be unique
}
Namespace(命名空间)

代表一个在同一个用路径名(例如:/chat)定义的作用域下连接的所有sockets。

客户端总是默认连接到/

namespace.name

  • (字符串)

命名空间的标识符属性。

namespace.connected

  • (对象)

所有连接到这个命名空间的的Socket对象的hash表,索引为其id。

namespace.emit(eventName[, args])

  • eventName(字符串)
  • args

向所有连接的客户端发送事件。以下两种写法等价:

var io = require('socket.io')();

io.emit("an event sent to all connected clients"); // main namespace

var chat = io.of('/chat');
chat.emit("an event sent to all connected in chat namespace");

namespace.clients(callback)

  • callback(函数)

获取所有连接到这个命名空间的客户端ID列表(如果适用可横跨所有节点)。

var io = require('socket.io')();
io.of('/chat').clients(function(error, clients) {
 if(error) throw error;
 console.log(clients); // => [PZDoMHjiu8PYfRiKAAAF, Anw2LatarvGVVXEIAAAD]
});

一个获取所有在命名空间某房间中客户端的例子:

var io = require('socket.io')();
io.of('/chat').in('general').clients(function(error, clients) {
 if(error) throw error;
 console.log(clients); // => [Anw2LatarvGVVXEIAAAD]
});

当利用广播时,默认所有客户端来自默认命名空间("/"):

var io = require('socket.io')();
io.clients(function (error, clients) {
 if(error) throw error;
 console.log(clients); // => [6em3d4TJP8Et9EMNAAAA, G5p55dHhGgUnLUctAAAB]
});

namespace.use(fn)

  • fn(函数)

寄存器中间件,每个接入的Socket都需要执行这个方法,并且可以接收socket和一个可选的用于在下一个寄存器中间件延迟执行的函数作为参数。

传递给中间件回调函数的错误会作为特殊的错误包发给客户端。

var io = require("socket.io")();
io.use(function(socket, next) {
 next(new Error("Authentication error"));
});

Event:'connect'

  • socket(Socket)socket和客户端连接

在客户端连接时触发。

Event:"connection"

Event:"connect"相同

Flag:"volatile"

给随后发送的事件设置一个标识表明如果客户端还没准备好接收消息则事件数据可能丢失(因为网网速慢或者其他问题,或者因为它们是通过长轮询连接的并且正处在一个请求-应答循环中)。

io.volatile.emit("an event", {some: "data"}); // the clients may or may not receive it

Flag:"local"

给一个随后发送的事件设置一个标识表明该事件数据只会广播到当前节点(当适用Redis adapter)。

io.local.emit("an event", {some: "data"});
Socket

一个Socket是和浏览器客户端交互的基类。一个Socket属于一个特定的Namespace(默认为/)且适用底层的Client进行通信。

值得一提的是Socket和实际的底层TCP/IPsocket没有直接关系,它只是一个类的类名而已。

在每个Namespace中,也可以定用于socket加入和离开的任意频道(叫做room)。这提供了一个方便的方式来向一组Sockets广播(见下方的socket#to)。

Socket类继承自EventEmitterSocket类重写了emit方法,并且没有修改EventEmitter中任何其他的方法。这里列出的所有方法同样都是EventEmitter的方法(除了emit之外),都由EventEmitter实现,这些文档都用于Eventmitter应用。

socket.id

  • (字符串)

来自客户端底层的该阶段独一无二的标识符。

socket.rooms

  • (对象)

客户端所在房间的字符串标识符组成的散列表,索引为房间名。

socket.client

  • (客户端)

底层客户端对象的一个引用。

socket.conn

  • (engine.Socket)

底层客户端传输连接(engine.io Socket对象)的一个引用。这允许访问I/O传输层,其仍然(主要)是TCP/IP socket的抽象。

socket.request

  • (请求)

返回源自底层engine.io Client的请求的一个引用。用于对请求头的访问,例如CookieUser-Agent

socket.use(fn)

寄存器中间件,每个接入的Socket都需要执行这个方法,并且可以接收该包和一个可选的用于在下一个寄存器中间件延迟执行的函数作为参数。

传递给中间件回调函数的错误会作为特殊的错误包发给客户端。

var io = require("socket.io")();
io.on("connection", function(socket) {
 socket.use(function(packet, next) {
  if(packet.doge === true) return next();
  next(new Error("not a doge error"));
 });
});

socket.send([...args][,ack])

  • args
  • ack(函数)
  • ReturnsSocket

发送一个message事件。见socket.emit(eventName[, ...args][, ack])

socket.emit(eventName[, ...args][,ack])

(重写后的EventEmitter.emit)

  • eventName(字符串)
  • args
  • ack(函数)
  • ReturnsSocket

通过字符串名字辨别发送的给socket的事件。可以包含任意其他的参数。支持所有序列化的数据结构,包括Buffer

socket.emit("hello", "world");
socket.emit("with-binary", 1, "2", {3: "4", 5: new Buffer(6)});

ack参数是可选的,它会在客户端应答时调用。

var io = require("socket.io")();
io.on("connection", function(client) {
 client.emit("an event", {some: "data"});
 
 client.emit("ferret", "tobi", function (data) {
  console.log(data); // data will be "woot"
 });

 // the client code
 // client.on("ferret", function (name, fn) {
 //  fn("woot");
 // });
});

socket.on(eventName, callback)

(继承自EventEmitter)

  • eventName(字符串)
  • callback(函数)
  • ReturnsSocket

给给定事件注册的新的处理程序。

socket.on("news", function (data) {
 console.log(data);
});

socket.once(eventName, listener)
socket.removeListener(eventName, listener)
socket.removeAllListeners([eventName])
socket.eventNames()

继承自EventEmitter(这里的方法不在这里赘述)。详情见Node.js文档的events模块。

socket.join(room[, callback])

  • room(字符串)
  • callback(函数)
  • Returnssocket链接

把客户端添加到roomerr签名可触发回调函数(如果有的话)。

io.on("connection", function(socket) {
 socket.join("room237", function () {
  console.log(socket.rooms); //[<socket.id>, "room 237"]
  // broadcast to everyone in the room
  io.to("room 237", "a new user has joined the room"); 
 });
});

加入房间的机制是由已配置的Adapter处理的(见上Server#adapter),默认为socket.io-adapter

为了方便起见,每个socket会根据它的id自动的加入某个房间(见Socket#id)。这使得向其他sockets广播消息变得容易:

io.on("connection", function (client) {
 client.on("say to someone", function (id, msg)) {
  // send a private message to the socket with the given id
  client.broadcast.to(id),.emit("my message", msg);
 }
});

socket.join(rooms[,callback])

  • rooms(数组)
  • callback(函数)
  • Returnssocket链接

把客户端加到房间列表中,err签名会触发回调函数(如果有的话)

socket.leave(room[, callback])

  • room(字符串)
  • callback(函数)
  • ReturnsSocket链接

room移除客户端,err签名会触发回调函数(如果有的话)

断开连接时将自动离开房间

socket.to(room)

  • room(字符串)
  • ReturnsSocket链接

为接下来的发送的事件设置标识符,该事件只会被广播到加入给定room的客户端处。

如果想发送到多个房间,可以调用多次。

var io = require("socket.io")();
io.on("connection", function (client) {
 // to one room
 client.to("others").emit("an event", {some: "data"});
 // to mutiple rooms
 client.to("room1").to("room2").emit("hello");
});

socket.in(room)

socket.to(room)相同

socket.compress(vaule)

  • value(布尔值)是否将以下的包压缩
  • Returnssocket链接

给接下来发送的事件加上标识符,即事件数据在值为true时会被压缩。在没有调用该方法是默认为true

socket.disconnect(close)

  • close(布尔值)是否断开底层连接
  • Returnssocket

断开该客户端。如果关闭的值为true,则断开底层连接。否则,只是断开命名空间。

Flag:"broadcast"

为接下来发送的事件设置标识符,该事件数据会广播至除了发送者之外的其他任何客户端。

var io = require("socket.io")();
io.on("connection", function (socket) {
 // everyone gets it but the sender
 socket.broadcast.emit("an event", {some: "data"});
});

flag: "volatile"

为接下来发送的事件设置一个标识符,表明如果客户端没准备好接收数据则接下来发送的数据可能丢失(由于网速过慢或其他问题,或者它们是通过长轮询机制连接且处于请求-应答循环的中间环节)。

var io = require("socket.io")();
io.on("connection", function(socket) {
 // the client may or may not receive it
 socket.volatile.emit("an event", {some: "data"});
});

Event:"disconnect"

  • reason(字符串) 断开的原因(客户端或服务器端)

当客户端即将断开时触发(但还没离开)

这些时保留的事件(connect, newListenerremoveListener)不能用作事件名称。

Client

Client类表示接入的传输(engine.io)连接。 一个Client可以和很多复合的属于不同NamespaceSocket有关系。

client.conn

  • (engine.Socket)

一个底层engine.io``socket连接的引用。

client.request

  • (Request)

对源于engine.io的连接的引用。用于获取请求头信息比如CookieUser-Agent