Node.js api 中文文档 - net


稳定度: 2 - 稳定

net模块为你提供了异步的网络调用的包装。它同时包含了创建服务器和客户端的函数。你可以通过require('net')来引入这个模块。

net.createServer([options][, connectionListener])

创建一个新的TCP服务器。connectionListener参数会被自动绑定为connection事件的监听器。

options是一个包含下列默认值的对象:

{
  allowHalfOpen: false,
  pauseOnConnect: false
}

如果allowHalfOpentrue,那么当另一端的socket发送一个FIN报文时socket并不会自动发送FIN报文。socket变得不可读,但是可写。你需要明确地调用end()方法。详见end事件。

如果pauseOnConnect是true,那么socket在每一次被连接时会暂停,并且不会读取数据。这允许在进程间被传递的连接不读取任何数据。如果要让一个被暂停的socket开始读取数据,调用resume()方法。

以下是一个应答服务器的例子,监听8124端口:

var net = require('net');
var server = net.createServer(function(c) { //'connection' listener
  console.log('client connected');
  c.on('end', function() {
    console.log('client disconnected');
  });
  c.write('hello\r\n');
  c.pipe(c);
});
server.listen(8124, function() { //'listening' listener
  console.log('server bound');
});

使用telnet测试:

telnet localhost 8124

想要监听socket``/tmp/echo.sock,只需改变倒数第三行:

server.listen('/tmp/echo.sock', function() { //'listening' listener

使用nc连接一个UNIX domain socket服务器:

nc -U /tmp/echo.sock

net.connect(options[, connectionListener])

net.createConnection(options[, connectionListener])

工厂函数,返回一个新的net.Socket实例,并且自动使用提供的options进行连接。

options会被同时传递给net.Socket构造函数和socket.connect方法。

参数connectListener将会被立即添加为connect事件的监听器。

下面是一个上文应答服务器的客户端的例子:

var net = require('net');
var client = net.connect({port: 8124},
    function() { //'connect' listener
  console.log('connected to server!');
  client.write('world!\r\n');
});
client.on('data', function(data) {
  console.log(data.toString());
  client.end();
});
client.on('end', function() {
  console.log('disconnected from server');
});

要连接socket``/tmp/echo.sock只需要改变第二行为:

var client = net.connect({path: '/tmp/echo.sock'});

net.connect(port[, host][, connectListener])

net.createConnection(port[, host][, connectListener])

工厂函数,返回一个新的net.Socket实例,并且自动使用指定的端口(port)和主机(host)进行连接。

如果host被省略,默认为localhost

参数connectListener将会被立即添加为connect事件的监听器。

net.connect(path[, connectListener])

net.createConnection(path[, connectListener])

工厂函数,返回一个新的unixnet.Socket实例,并且自动使用提供的路径(path)进行连接。

参数connectListener将会被立即添加为connect事件的监听器。

Class: net.Server

这个类用于创建一个TCP或本地服务器。

server.listen(port[, hostname][, backlog][, callback])

开始从指定端口和主机名接收连接。如果省略主机名,那么如果IPv6可用,服务器会接受从任何IPv6地址(::)来的链接,否则为任何IPv4地址(0.0.0.0)。如果端口为0那么将会为其设置一个随机端口。

积压量backlog是连接等待队列的最大长度。实际长度由你的操作系统的sysctl设置决定(如linux中的tcp_max_syn_backlogsomaxconn)。这个参数的默认值是511(不是512)。

这个函数式异步的。当服务器绑定了指定端口后,listening事件将会被触发。最后一个参数callback将会被添加为listening事件的监听器。

有些用户可能遇到的情况是收到EADDRINUSE错误。这意味着另一个服务器已经使用了该端口。一个解决的办法是等待一段时间后重试。

server.on('error', function (e) {
  if (e.code == 'EADDRINUSE') {
    console.log('Address in use, retrying...');
    setTimeout(function () {
      server.close();
      server.listen(PORT, HOST);
    }, 1000);
  }
});

(注意,node.js中所有的socket都已经设置了SO_REUSEADDR

server.listen(path[, callback])

  • path String
  • callback Function

启动一个本地socket服务器,监听指定路径(path)上的连接。

这个函数式异步的。当服务器监听了指定路径后,listening事件将会被触发。最后一个参数callback将会被添加为listening事件的监听器。

在UNIX中,local domain经常被称作UNIX domainpath是一个文件系统路径名。它在被创建时会受相同文件名约定(same naming conventions)的限制并且进行权限检查(permissions checks)。它在文件系统中可见,并且在被删除前持续存在。

在Windows中,local doamin使用一个命名管道(named pipe)实现。path必须指向\\?\pipe\\\.\pipe\.中的一个条目,但是后者可能会做一些命名管道的处理,如处理..序列。除去表现,命名管道空间是平坦的(flat)。管道不会持续存在,它们将在最后一个它们的引用关闭后被删除。不要忘记,由于JavaScript的字符串转义,你必须在指定path时使用双反斜杠:

net.createServer().listen(
    path.join('\\\\?\\pipe', process.cwd(), 'myctl'))

server.listen(handle[, callback])

  • handle Object
  • callback Function

handle对象可以被设置为一个服务器或一个socket(或者任意以下划线开头的成员_handle),或者一个{fd: <n>}对象。

这将使得服务器使用指定句柄接受连接,但它假设文件描述符或句柄已经被绑定至指定的端口或域名socket

在Windows下不支持监听一个文件描述符。

这个函数式异步的。当服务器已被绑定后,listening事件将会被触发。最后一个参数callback将会被添加为listening事件的监听器。

server.listen(options[, callback])

  • options Object

    • port Number 可选
    • host String 可选
    • backlog Number 可选
    • path String 可选
    • exclusive Boolean 可选
  • callback Function 可选

porthostbacklog属性,以及可选的callback函数,与server.listen(port, [host], [backlog], [callback])中表现一致。path可以被指定为一个UNIX socket

如果exclusivefalse(默认),那么工作集群(cluster workers)将会使用相同的底层句柄,处理的连接的职责将会被它们共享。如果exclusivetrue,那么句柄是不被共享的,企图共享将得到一个报错的结果。下面是一个监听独有端口的例子:

server.listen({
  host: 'localhost',
  port: 80,
  exclusive: true
});

server.close([callback])

使服务器停止接收新的连接并且保持已存在的连接。这个函数式异步的,当所有的连接都结束时服务器会最终关闭,并处罚一个close事件。可选的,你可以传递一个回调函数来监听close事件。如果传递了,那么它的唯一的第一个参数将表示任何可能潜在发生的错误。

server.address()

返回服务器绑定的地址,协议族名和端口通过操作系统报告。对查找操作系统分配的地址哪个端口被分配非常有用。返回一个有三个属性的对象。如{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

例子:

var server = net.createServer(function (socket) {
  socket.end("goodbye\n");
});

// grab a random port.
server.listen(function() {
  address = server.address();
  console.log("opened server on %j", address);
});

listening事件触发前,不要调用server.address()方法。

server.unref()

调用一个server对象的unref方法将允许如果它是事件系统中唯一活跃的服务器,程序将会退出。如果服务器已经被调用过这个方法,那么再次调用这个方法将不会有任何效果。

返回server对象。

server.ref()

unref相反,在一个已经被调用unref方法的server中调用ref方法,那么如果它是唯一活跃的服务器时,程序将不会退出(默认)。如果服务器已经被调用过这个方法,那么再次调用这个方法将不会有任何效果。

返回server对象。

server.maxConnections

设置了这个属性后,服务器的连接数达到时将会开始拒绝连接。

一旦socket被使用child_process.fork()传递给了子进程,这个属性就不被推荐去设置。

server.connections

这个函数已经被弃用。请使用server.getConnections()替代。

服务器的当前连接数。

当使用child_process.fork()传递一个socket给子进程时,这个属性将变成null。想要得到正确的结果请使用server.getConnections

server.getConnections(callback)

异步地去获取服务器的当前连接数,在socket被传递给子进程时仍然可用。

回调函数的两个参数是errcount

net.Server是一个具有以下事件的EventEmitter

Event: 'listening'

当调用server.listen后,服务器已被绑定时触发。

Event: 'connection'

  • Socket object 连接对象

当新的连接产生时触发。socket是一个net.Socket实例。

Event: 'close'

当服务器关闭时触发。注意如果服务器中仍有连接存在,那么这个事件会直到所有的连接都关闭后才触发。

Event: 'error'

  • Error Object

当发生错误时触发。close事件将会在它之后立即触发。参阅server.listen

Class: net.Socket

这个对象是一个TCP或本地socket的抽象。net.Socket实例实现了双工流(duplex Stream)接口。它可以被使用者创建,并且被作为客户端(配合connect())使用。或者也可以被node.js创建,并且通过服务器的connection事件传递给使用者。

new net.Socket([options])

创建一个新的socket对象。

options是一个有以下默认值的对象:

{ fd: null
  allowHalfOpen: false,
  readable: false,
  writable: false
}

fd允许你使用一个指定的已存在的socket文件描述符。设置readable 和/或 writabletrue将允许从这个socket中读 和/或 写(注意,仅在传递了passed时可用)。关于allowHalfOpen,参阅createServer()end事件。

socket.connect(options[, connectListener])

从给定的socket打开一个连接。

对于TCPsocketoptions参数需是一个包含以下属性的对象:

  • port: 客户端需要连接的端口(必选)。

  • host: 客户端需要连接的主机(默认:'localhost')

  • localAddress: 将要绑定的本地接口,为了网络连接。

  • localPort: 将要绑定的本地端口,为了网络连接。

  • family : IP协议族版本,默认为4

  • lookup : 自定义查找函数。默认为dns.lookup

对于本地domain socketoptions参数需是一个包含以下属性的对象:

  • path: 客户端需要连接的路径(必选)。

通常这个方法是不需要的,因为通过net.createConnection打开socket。只有在你自定义了socket时才使用它。

这个函数式异步的,当connect事件触发时,这个socket就被建立了。如果在连接的过程有问题,那么connect事件将不会触发,error将会带着这个异常触发。

connectListener参数会被自动添加为connect事件的监听器。

socket.connect(port[, host][, connectListener])

socket.connect(path[, connectListener])

参阅socket.connect(options[, connectListener])

socket.bufferSize

net.Socket的属性,用于socket.write()。它可以帮助用户获取更快的运行速度。计算机不能一直保持大量数据被写入socket的状态,网络连接可以很慢。node.js在内部会排队等候数据被写入socekt并确保传输连接上的数据完好。 (内部实现为:轮询socekt的文件描述符等待它为可写)。

内部缓存的可能结果是内存使用会增长。这个属性展示了缓存中还有多少待写入的字符(字符的数目约等于要被写入的字节数,但是缓冲区可能包含字符串,而字符串是惰性编码的,所以确切的字节数是未知的)。

遇到数值很大或增长很快的bufferSize时,应当尝试使用pause()resume()来控制。

socket.setEncoding([encoding])

设置socket的编码作为一个可读流。详情参阅stream.setEncoding()

socket.write(data[, encoding][, callback])

在套接字上发送数据。第二个参数指定了字符串的编码,默认为UTF8。

如果所有数据成功被刷新至了内核缓冲区,则返回true。如果所有或部分数据仍然在用户内存中排队,则返回falsedrain事件将会被触发当buffer再次为空时。

当数据最终被写入时,callback回调函数将会被执行,但可能不会马上执行。

socket.end([data][, encoding])

半关闭一个socket。比如,它发送一个FIN报文。可能服务器仍然在发送一些数据。

如果data参数被指定,那么等同于先调用socket.write(data, encoding),再调用socket.end()

socket.destroy()

确保这个socket上没有I/O活动发生。只在发生错误情况才需要(如处理错误)。

socket.pause()

暂停数据读取。data事件将不会再触发。对于控制上传非常有用。

socket.resume()

用于在调用pause()后,恢复数据读取。

socket.setTimeout(timeout[, callback])

如果sockettimeout毫秒中没有活动后,设置其为超时。默认情况下,net.Socket没有超时。

当超时发生,socket会收到一个timeout事件,但是连接将不会被断开。用户必须手动地调用end()destroy()方法。

如果timeout0,那么现有的超时将会被禁用。

可选的callback参数就会被自动添加为timeout事件的监听器。

返回一个socket

socket.setNoDelay([noDelay])

警用纳格算法(Nagle algorithm)。默认情况下TCP连接使用纳格算法,它们的数据在被发送前会被缓存。设置noDelaytrue将会在每次socket.write()时立刻发送数据。noDelay默认为true

返回一个socket

socket.setKeepAlive([enable][, initialDelay])

启用/警用长连接功能,并且在第一个在闲置socket的长连接probe被发送前,可选得设置初始延时。enable默认为false

设定initialDelay(毫秒),来设定在收到的最后一个数据包和第一个长连接probe之间的延时。将initialDelay设成0会让值保持不变(默认值或之前所设的值)。默认为0

返回一个socket

socket.address()

返回绑定的地址,协议族名和端口通过操作系统报告。对查找操作系统分配的地址哪个端口被分配非常有用。返回一个有三个属性的对象。如{ port: 12346, family: 'IPv4', address: '127.0.0.1' }

socket.unref()

调用一个socket对象的unref方法将允许如果它是事件系统中唯一活跃的socket,程序将会退出。如果socket已经被调用过这个方法,那么再次调用这个方法将不会有任何效果。

返回socket对象。

socket.ref()

unref相反,在一个已经被调用unref方法的socket中调用ref方法,那么如果它是唯一活跃的socket时,程序将不会退出(默认)。如果socket已经被调用过这个方法,那么再次调用这个方法将不会有任何效果。

返回socket对象。

socket.remoteAddress

远程IP地址字符串。例如,'74.125.127.100''2001:4860:a005::68'

socket.remoteFamily

远程IP协议族字符串。例如,'IPv4''IPv6'

socket.remotePort

远程端口数值。例如,8021

socket.localAddress

远程客户端正连接的本地IP地址字符串。例如,如果你正在监听'0.0.0.0'并且客户端连接在'192.168.1.1',其值将为'192.168.1.1'

socket.localPort

本地端口数值。例如,8021

socket.bytesRead

接受的字节数。

socket.bytesWritten

发送的字节数。

net.Socket net.Socket实例是一个包含以下事件的EventEmitter

Event: 'lookup'

在解析主机名后,连接主机前触发。对UNIX socket不适用。

  • err {Error | Null} 错误对象,参阅 dns.lookup()
  • address {String} IP地址
  • family {String | Null} 地址类型。参阅'dns.lookup()`

Event: 'connect'

socket连接成功建立后触发。参阅connect()

Event: 'data'

  • Buffer object

在接受到数据后触发。参数将会是一个Buffer或一个字符串。数据的编码由socket.setEncoding()设置(更多详细信息请查看可读流章节)。

注意,当socket触发data事件时,如果没有监听器存在。那么数据将会丢失。

Event: 'end'

当另一端的socket发送一个FIN报文时触发。

默认情况(allowHalfOpen == false)下,一旦一个socket的文件描述符被从它的等待写队列(pending write queue)中写出,socket会销毁它。但是,当设定allowHalfOpen == true后,socket不会在它这边自动调用end(),允许用户写入任意数量的数据,需要注意的是用户需要在自己这边调用end()

Event: 'timeout'

socket因不活动而超时时触发。这只是来表示socket被限制。用户必须手动关闭连接。

参阅socket.setTimeout()

Event: 'drain'

当写缓冲为空时触发。可以被用来控制上传流量。

参阅socket.write()的返回值。

Event: 'error'

  • Error object

当发生错误时触发。close事件会紧跟着这个事件触发。

Event: 'close'

  • had_error 如果socket有一个传输错误时为true

socket完全关闭时触发。参数had_error是一个表示socket是否是因为传输错误而关闭的布尔值。

net.isIP(input)

测试input是否是一个IP地址。如果是不合法字符串时,会返回0。如果是IPv4地址则返回4,是IPv6地址则返回6

net.isIPv4(input)

如果input是一个IPv4地址则返回true,否则返回false

net.isIPv6(input)

如果input是一个IPv6地址则返回true,否则返回false

更多Node.js教程

学习更多Node.js教程