🔥码云GVP开源项目 12k star Uniapp+ElementUI 功能强大 支持多语言、二开方便! 广告
### 稳定度: 2 - 稳定 `net`模块为你提供了异步的网络调用的包装。它同时包含了创建服务器和客户端的函数。你可以通过`require('net')`来引入这个模块。 #### net.createServer([options][, connectionListener]) 创建一个新的TCP服务器。`connectionListener`参数会被自动绑定为`connection`事件的监听器。 `options`是一个包含下列默认值的对象: ~~~ { allowHalfOpen: false, pauseOnConnect: false } ~~~ 如果`allowHalfOpen`是`true`,那么当另一端的`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]) 工厂函数,返回一个新的unix`net.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_backlog`和`somaxconn`)。这个参数的默认值是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); } }); ~~~ (注意,`io.js`中所有的`socket`都已经设置了`SO_REUSEADDR`) #### server.listen(path[, callback]) - path String - callback Function 启动一个本地`socket`服务器,监听指定路径(`path`)上的连接。 这个函数式异步的。当服务器监听了指定路径后,`listening`事件将会被触发。最后一个参数`callback`将会被添加为`listening`事件的监听器。 在UNIX中,`local domain`经常被称作`UNIX domain`。`path`是一个文件系统路径名。它在被创建时会受相同文件名约定(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 可选 `port`,`host`和`backlog`属性,以及可选的`callback`函数,与`server.listen(port, [host], [backlog], [callback])`中表现一致。`path`可以被指定为一个UNIX `socket`。 如果`exclusive`是`false`(默认),那么工作集群(cluster workers)将会使用相同的底层句柄,处理的连接的职责将会被它们共享。如果`exclusive`是`true`,那么句柄是不被共享的,企图共享将得到一个报错的结果。下面是一个监听独有端口的例子: ~~~ 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`被传递给子进程时仍然可用。 回调函数的两个参数是`err`和`count`。 ### `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()`)使用。或者也可以被`io.js`创建,并且通过服务器的`connection`事件传递给使用者。 #### new net.Socket([options]) 创建一个新的`socket`对象。 `options`是一个有以下默认值的对象: ~~~ { fd: null allowHalfOpen: false, readable: false, writable: false } ~~~ `fd`允许你使用一个指定的已存在的`socket`文件描述符。设置`readable` 和/或 `writable`为`true`将允许从这个`socket`中读 和/或 写(注意,仅在传递了`passed`时可用)。关于`allowHalfOpen`,参阅`createServer()`和`end`事件。 #### socket.connect(options[, connectListener]) 从给定的`socket`打开一个连接。 对于TCP`socket`,`options`参数需是一个包含以下属性的对象: - port: 客户端需要连接的端口(必选)。 - host: 客户端需要连接的主机(默认:'localhost') - localAddress: 将要绑定的本地接口,为了网络连接。 - localPort: 将要绑定的本地端口,为了网络连接。 - family : IP协议族版本,默认为`4`。 - lookup : 自定义查找函数。默认为`dns.lookup`。 对于本地domain `socket`,`options`参数需是一个包含以下属性的对象: - 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`的状态,网络连接可以很慢。`io.js`在内部会排队等候数据被写入`socekt`并确保传输连接上的数据完好。 (内部实现为:轮询`socekt`的文件描述符等待它为可写)。 内部缓存的可能结果是内存使用会增长。这个属性展示了缓存中还有多少待写入的字符(字符的数目约等于要被写入的字节数,但是缓冲区可能包含字符串,而字符串是惰性编码的,所以确切的字节数是未知的)。 遇到数值很大或增长很快的`bufferSize`时,应当尝试使用`pause()`和`resume()`来控制。 #### socket.setEncoding([encoding]) 设置`socket`的编码作为一个可读流。详情参阅`stream.setEncoding()`。 #### socket.write(data[, encoding][, callback]) 在套接字上发送数据。第二个参数指定了字符串的编码,默认为UTF8。 如果所有数据成功被刷新至了内核缓冲区,则返回`true`。如果所有或部分数据仍然在用户内存中排队,则返回`false`。`drain`事件将会被触发当`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]) 如果`socket`在`timeout`毫秒中没有活动后,设置其为超时。默认情况下,`net.Socket`没有超时。 当超时发生,`socket`会收到一个`timeout`事件,但是连接将不会被断开。用户必须手动地调用`end()`或`destroy()`方法。 如果`timeout`是`0`,那么现有的超时将会被禁用。 可选的`callback`参数就会被自动添加为`timeout`事件的监听器。 返回一个`socket`。 #### socket.setNoDelay([noDelay]) 警用纳格算法(Nagle algorithm)。默认情况下TCP连接使用纳格算法,它们的数据在被发送前会被缓存。设置`noDelay`为`true`将会在每次`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 远程端口数值。例如,`80`或`21`。 #### socket.localAddress 远程客户端正连接的本地IP地址字符串。例如,如果你正在监听`'0.0.0.0'`并且客户端连接在`'192.168.1.1'`,其值将为`'192.168.1.1'`。 #### socket.localPort 本地端口数值。例如,`80`或`21`。 #### 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`。