Node.js UDP / Datagram Sockets模块

  • UDP / Datagram Sockets
    • Class: dgram.Socket
      • Event: ‘close’
      • Event: ‘error’
      • Event: ‘listening’
      • Event: ‘message’
      • socket.addMembership(multicastAddress[, multicastInterface])
      • socket.address()
      • socket.bind([port][, address][, callback])
      • socket.bind(options[, callback])
      • socket.close([callback])
      • socket.dropMembership(multicastAddress[, multicastInterface])
      • socket.send(msg, [offset, length,] port, address[, callback])
      • socket.setBroadcast(flag)
      • socket.setMulticastLoopback(flag)
      • socket.setMulticastTTL(ttl)
      • socket.setTTL(ttl)
      • socket.ref()
      • socket.unref()
      • Change to asynchronous socket.bind() behavior
    • dgram module functions
      • dgram.createSocket(options[, callback])
      • dgram.createSocket(type[, callback])

The dgram module provides an implementation of UDP Datagram sockets.

dgram模块提供了一个UDP数据报文套接字的实现。

const dgram = require('dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.log(`server error:\n${err.stack}`);
  server.close();
});

server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});

server.on('listening', () => {
  var address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(41234);
// server listening 0.0.0.0:41234

Class: dgram.Socket

Added in: v0.1.99
The dgram.Socket object is an EventEmitter that encapsulates the datagram functionality.

New instances of dgram.Socket are created using dgram.createSocket(). The new keyword is not to be used to create dgram.Socket instances.

dgram.Socket对象是一个事件发生器,囊括了数据报文的功能。

dgram.Socket实例使用dgram.createSocket()来创建。这个新的关键字不能被用来创建dgram.Socket实例。

Event: ‘close’

Added in: v0.1.99
The ‘close’ event is emitted after a socket is closed with close(). Once triggered, no new ‘message’ events will be emitted on this socket.

当套接字被关闭后会触发’close’事件。一旦触发该事件,在该套接字上就不会有新的’message’ 事件被触发了。

Event: ‘error’

Added in: v0.1.99

  • exception

The ‘error’ event is emitted whenever any error occurs. The event handler function is passed a single Error object.

任何错误产生时都会触发’error’事件。事件处理函数只会传递一个错误对象。

Event: ‘listening’

Added in: v0.1.99
The ‘listening’ event is emitted whenever a socket begins listening for datagram messages. This occurs as soon as UDP sockets are created.

当套接字开始监听数据报报文时,’listening’事件就会被触发。一旦UDP套接字被创建就会发生该事件。

Event: ‘message’

Added in: v0.1.99

  • msg - The message
  • rinfo - Remote address information

    The ‘message’ event is emitted when a new datagram is available on a socket. The event handler function is passed two arguments: msg and rinfo. The msg argument is a Buffer and rinfo is an object with the sender’s address information provided by the address, family and port properties:

    • msg - 消息
    • rinfo - 远程地址信息

      当套接字上有一个新的可用的数据包文时,’message’事件就会被触发。该事件处理函数有2个参数:msgrinfomsg参数是一个字节缓冲区,然后rinfo是一个带发送者地址信息的对象,可以提供地址、协议族、断开属性。

      socket.on('message', (msg, rinfo) => {
        console.log('Received %d bytes from %s:%d\n',
                    msg.length, rinfo.address, rinfo.port);
      });

      socket.addMembership(multicastAddress[, multicastInterface])

      Added in: v0.6.9

      • multicastAddress
      • multicastInterface , Optional

      Tells the kernel to join a multicast group at the given multicastAddress and multicastInterface using the IP_ADD_MEMBERSHIP socket option. If the multicastInterface argument is not specified, the operating system will choose one interface and will add membership to it. To add membership to every available interface, call addMembership multiple times, once per interface.

      告诉内核在给定的多播地址和多播接口上使用IP_ADD_MEMBERSHIP套接字选项,去加入一个多播组。如果不指定多播接口参数,操作系统就会自己选择一个接口,然后将成员添加到它上面。通过在每一个接口一次addMembership的多次调用,可以将成员添加到每一个可用的接口上。

      socket.address()

      Added in: v0.1.99
      Returns an object containing the address information for a socket. For UDP sockets, this object will contain address, family and port properties.

      返回一个对象包含套接字的地址信息。对于UDP套接字,该对象将会包含地址、协议族和端口属性。

      socket.bind([port][, address][, callback])

      Added in: v0.1.99

      • port - Integer, Optional
      • address , Optional
      • callback with no parameters, Optional. Called when binding is complete.

      For UDP sockets, causes the dgram.Socket to listen for datagram messages on a named port and optional address. If port is not specified, the operating system will attempt to bind to a random port. If address is not specified, the operating system will attempt to listen on all addresses. Once binding is complete, a ‘listening’ event is emitted and the optional callback function is called.

      Note that specifying both a ‘listening’ event listener and passing a callback to the socket.bind() method is not harmful but not very useful.

      A bound datagram socket keeps the Node.js process running to receive datagram messages.

      If binding fails, an ‘error’ event is generated. In rare case (e.g. attempting to bind with a closed socket), an Error may be thrown.

      Example of a UDP server listening on port 41234:

      对于UDP套接字,会使得dgram.Socket在一个指定的端口和一个可选的地址上监听数据报文,它们会传递给options对象的属性作为该方法的第一个参数。如果端口未指定,操作系统就会尝试去绑定一个随机的端口,如果地址未指定,操作系统就会尝试在所有地址上进行监听。一旦绑定操作完成,listening事件就会被触发,然后可选的回调函数就会被调用。

      注意:指定一个’listening’的事件监听器并且传递一个回调函数给socket.bind()方法虽然无害但也不是很有用。

      一个绑定的套接字会让Node.js保持运行来接收数据报文。

      如果绑定失败,就会生成一个错误事件。一个罕见的情况(例如尝试去绑定一个已经关闭的套接字),就会抛出错误。

      一个监听41234端口的UDP服务器的例子:

      const dgram = require('dgram');
      const server = dgram.createSocket('udp4');
      
      server.on('error', (err) => {
        console.log(`server error:\n${err.stack}`);
        server.close();
      });
      
      server.on('message', (msg, rinfo) => {
        console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
      });
      
      server.on('listening', () => {
        var address = server.address();
        console.log(`server listening ${address.address}:${address.port}`);
      });
      
      server.bind(41234);
      // server listening 0.0.0.0:41234

      socket.bind(options[, callback])

      Added in: v0.11.14

      • options - Required. Supports the following properties:
      • port - Required.
      • address - Optional.
      • exclusive - Optional.
      • callback - Optional.
      • For UDP sockets, causes the dgram.Socket to listen for datagram messages on a named port and optional address that are passed as properties of an options object passed as the first argument. If port is not specified, the operating system will attempt to bind to a random port. If address is not specified, the operating system will attempt to listen on all addresses. Once binding is complete, a ‘listening’ event is emitted and the optional callback function is called.

        The options object may contain an additional exclusive property that is use when using dgram.Socket objects with the cluster module. When exclusive is set to false (the default), cluster workers will use the same underlying socket handle allowing connection handling duties to be shared. When exclusive is true, however, the handle is not shared and attempted port sharing results in an error.

        An example socket listening on an exclusive port is shown below.

        对于UDP套接字,会使得dgram.Socket在一个指定的端口和一个可选的地址上监听数据报文,它们会传递给options对象的属性作为该方法的第一个参数。如果端口未指定,操作系统就会尝试去绑定一个随机的端口,如果地址未指定,操作系统就会尝试在所有地址上进行监听。一旦绑定操作完成,listening事件就会被触发,然后可选的回调函数就会被调用。

        该参数对象可以包含一个额外的排外的属性,当使用dgram.Socket对象的cluseter模块时需要用到。当exclusive被设置为假(默认值),cluster工作者将会使用相同的底层套接字来处理,并且在职责上共享连接。当exclusive被设置为真的时候,相反,不会功效处理并且尝试共享端口的操作都会导致错误。

        一个监听除了某个端口的套接字如下:

        socket.bind({
          address: 'localhost',
          port: 8000,
          exclusive: true
        });

        socket.close([callback])

        Added in: v0.1.99
        Close the underlying socket and stop listening for data on it. If a callback is provided, it is added as a listener for the ‘close’ event.

        关闭下层的套接字并停止在它上面监听数据。如果提供回调函数,它就会作为’close’事件的监听器被添加。

        socket.dropMembership(multicastAddress[, multicastInterface])

        Added in: v0.6.9

        • multicastAddress
        • multicastInterface , Optional

        Instructs the kernel to leave a multicast group at multicastAddress using the IP_DROP_MEMBERSHIP socket option. This method is automatically called by the kernel when the socket is closed or the process terminates, so most apps will never have reason to call this.

        If multicastInterface is not specified, the operating system will attempt to drop membership on all valid interfaces.

        命令内核使用IP_DROP_MEMBERSHIP选项删除一个在某个多播地址上的多播组。当套接字被关闭或进程被终止时,该方法由内核自动调用,因此大部分应用程序没有理由去调用它。

        如果multicastInterface未指定,操作系统就会尝试删除所有合法接口上的成员。

        socket.send(msg, [offset, length,] port, address[, callback])

        Added in: v0.1.99

        • msg | | Message to be sent
        • offset Integer. Optional. Offset in the buffer where the message starts.
        • length Integer. Optional. Number of bytes in the message.
        • port Integer. Destination port.
        • address Destination hostname or IP address.
        • callback Called when the message has been sent. Optional.

        Broadcasts a datagram on the socket. The destination port and address must be specified.

        The msg argument contains the message to be sent. Depending on its type, different behavior can apply. If msg is a Buffer, the offset and length specify the offset within the Buffer where the message begins and the number of bytes in the message, respectively. If msg is a String, then it is automatically converted to a Buffer with ‘utf8’ encoding. With messages that contain multi-byte characters, offset and length will be calculated with respect to byte length and not the character position. If msg is an array, offset and length must not be specified.

        The address argument is a string. If the value of address is a host name, DNS will be used to resolve the address of the host. If the address is not specified or is an empty string, ‘127.0.0.1’ or ‘::1’ will be used instead.

        If the socket has not been previously bound with a call to bind, the socket is assigned a random port number and is bound to the “all interfaces” address (‘0.0.0.0’ for udp4 sockets, ‘::0’ for udp6 sockets.)

        An optional callback function may be specified to as a way of reporting DNS errors or for determining when it is safe to reuse the buf object. Note that DNS lookups delay the time to send for at least one tick of the Node.js event loop.

        The only way to know for sure that the datagram has been sent is by using a callback. If an error occurs and a callback is given, the error will be passed as the first argument to the callback. If a callback is not given, the error is emitted as an ‘error’ event on the socket object.

        Offset and length are optional, but if you specify one you would need to specify the other. Also, they are supported only when the first argument is a Buffer.

        Example of sending a UDP packet to a random port on localhost;

        • msg | | 待发送的消息。
        • offset 整型。可选参数。消息起始位置在字节数组中的偏移量。
        • length 整型。可选参数。消息中总共的字节数。
        • port 整型。目标端口。
        • address 目标主机名或者IP地址
        • callback 当消息被发送之后会被调用。可选的。

        在套接字上广播一个数据报文。目标端口和地址必须被指定。

        msg参数包含了将要发送的消息。根据其类型会采用不同行为。如果msg是一个字节数组,offset

        length分别指定了消息在字节数组内的偏移和消息的字节数。如果msg是一个字符串,它会使用utf-8编码被自动转化为字节数组。如果消息包含多字节字符,offsetlength会被计算为针对字节的长度,而不是字符的位置。如果msg是一个数组,offsetlength就不应该被指定了。

        address参数是一个字符串。如果address是一个主机名,DNS将会解析该主机的地址。如果地址未被指定或者是一个空串,就会使用127.0.0.1::1来代替。

        如果套接字之前没有调用bind()函数来绑定,该套接字就会被随机分配一个端口,然后绑定到所有的接口地址上(udp4套接字是’0.0.0.0’, udp6套接字是’::0’)

        当可以安全地重用buf对象时,可以指定一个可选的callback函数,用来报告DNS确定错误。注意:DNS查询结果会至少延迟一个Node.js事件循环才被发送。

        唯一能确定数据报文被发送的方式只有使用回调函数。如果产生了错误并且有提供一个回调函数,该错误就会被传递到回调函数的第一个参数中。如果没有给回调函数,在套接字对象中,错误就会被发送到’error’时间上。

        offsetlength都是可选的,但是如果你指定了一个你就必须指定另一个。并且只有当第一个参数是字节数组时,它们能才被支持。

        发送一个UDP包到一个本地的随机端口的例子。
        我认为这里原文有误,由于没有bind,应该是从随机的端口发送到一个指定的端口

        const dgram = require('dgram');
        const message = Buffer.from('Some bytes');
        const client = dgram.createSocket('udp4');
        client.send(message, 41234, 'localhost', (err) => {
          client.close();
        });

        Example of sending a UDP packet composed of multiple buffers to a random port on localhost;

        发送一个由多个字节缓冲区组成的UDP包到本地的随机端口的例子。
        我认为这里原文有误,由于没有bind,应该是从随机的端口发送到一个指定的端口

        const dgram = require('dgram');
        const buf1 = Buffer.from('Some ');
        const buf2 = Buffer.from('bytes');
        const client = dgram.createSocket('udp4');
        client.send([buf1, buf2], 41234, 'localhost', (err) => {
          client.close();
        });

        Sending multiple buffers might be faster or slower depending on your application and operating system: benchmark it. Usually it is faster.

        发送多个字节数组可能快也可能慢,依赖于你的应用程序和操作系统:基准。通常它会更快一点。

        A Note about UDP datagram size

        The maximum size of an IPv4/v6 datagram depends on the MTU (Maximum Transmission Unit) and on the Payload Length field size.

        • The Payload Length field is 16 bits wide, which means that a normal payload exceed 64K octets including the internet header and data (65,507 bytes = 65,535 − 8 bytes UDP header − 20 bytes IP header); this is generally true for loopback interfaces, but such long datagram messages are impractical for most hosts and networks.

        • The MTU is the largest size a given link layer technology can support for datagram messages. For any link, IPv4 mandates a minimum MTU of 68 octets, while the recommended MTU for IPv4 is 576 (typically recommended as the MTU for dial-up type applications), whether they arrive whole or in fragments.

        For IPv6, the minimum MTU is 1280 octets, however, the mandatory minimum fragment reassembly buffer size is 1500 octets. The value of 68 octets is very small, since most current link layer technologies, like Ethernet, have a minimum MTU of 1500.

        It is impossible to know in advance the MTU of each link through which a packet might travel. Sending a datagram greater than the receiver MTU will not work because the packet will get silently dropped without informing the source that the data did not reach its intended recipient.

        IPv4/v6数据报文的最大长度依赖于MTU(最大传输单元)和载荷长度域的大小。

        载荷长度域的宽度是16比特,它意味着一个正常的载荷大小可以超过64K字节,包括因特网头部和数据部分 (65,507 bytes = 65,535 − 8 bytes UDP header − 20 bytes IP header); 它在环回接口上通常被允许,但是这么长的数据报文对于大多数主机和网络来说是不切实际的。

        MTU是给定的链接层技术可以支持的数据报文的最大长度。对于任何连接,IPv4要求最小的MTU是68字节,而推荐的IPv4的MTU是576(通常是拨号类型的应用推荐的MTU),不管它是整个到达还是分片到达。

        对于IPv6,最小MTU是1280字节,然而要求的从新组装的最小分片是字节大小是1500字节。68字节是非常小的,因为大部分现在链接层技术,像Ethernet,最小MTU都是1500。

        不可能提前知道包可能经过的每一个链路的MTU。发送的数据包大于接收的MTU会导致数据包不起作用,因为数据包会被默默地丢弃而不会通知源头数据未到达它的预定接收者。

        socket.setBroadcast(flag)

        Added in: v0.6.9

        • flag

        Sets or clears the SO_BROADCAST socket option. When set to true, UDP packets may be sent to a local interface’s broadcast address.

        设置或清除SO_BROADCAST套接字选项,当被设置为真时,UDP包就可以被发送到本地接口的广播地址了。

        socket.setMulticastLoopback(flag)

        Added in: v0.3.8

        • flag

        Sets or clears the IP_MULTICAST_LOOP socket option. When set to true, multicast packets will also be received on the local interface.

        设置或清除IP_MULTICAST_LOOP套接字选项,当被设置为真时,在本地接口上就可以接收多播包。

        socket.setMulticastTTL(ttl)

        Added in: v0.3.8

        • ttl Integer

        Sets the IP_MULTICAST_TTL socket option. While TTL generally stands for “Time to Live”, in this context it specifies the number of IP hops that a packet is allowed to travel through, specifically for multicast traffic. Each router or gateway that forwards a packet decrements the TTL. If the TTL is decremented to 0 by a router, it will not be forwarded.

        The argument passed to to socket.setMulticastTTL() is a number of hops between 0 and 255. The default on most systems is 1 but can vary.

        设置IP_MULTICAST_TTL套接字参数。TTL通常代表”生存时间”,在该上下文中,它指定了包允许经过的IP跳数,尤其是多播通信。每一个转发包的路由器或者网关都会递减TTL。如果TTL被路由器减到0,它就不会被继续转发了。改变TTL的值通常是网络探测或者广播的时候干的事。

        socket.setMulticastTTL()的参数是一个在0到255之间的数字。在大部分系统上是1,但是该值可以改变。

        socket.setTTL(ttl)

        Added in: v0.1.101

        • ttl Integer

        Sets the IP_TTL socket option. While TTL generally stands for “Time to Live”, in this context it specifies the number of IP hops that a packet is allowed to travel through. Each router or gateway that forwards a packet decrements the TTL. If the TTL is decremented to 0 by a router, it will not be forwarded. Changing TTL values is typically done for network probes or when multicasting.

        The argument to socket.setTTL() is a number of hops between 1 and 255. The default on most systems is 64 but can vary.

        设置IP_TTL套接字选项。TTL通常代表”生存时间”,在该上下文中,它指定了包允许经过的IP跳数。每一个转发包的路由器或者网关都会递减TTL。如果TTL被路由器减到0,它就不会被继续转发了。改变TTL的值通常是网络探测或者广播的时候干的事。

        socket.setTTL()的参数是一个在1到255之间的数字。在大部分系统上是64,但是该值可以改变。

        socket.ref()

        Added in: v0.9.1
        By default, binding a socket will cause it to block the Node.js process from exiting as long as the socket is open. The socket.unref() method can be used to exclude the socket from the reference counting that keeps the Node.js process active. The socket.ref() method adds the socket back to the reference counting and restores the default behavior.

        Calling socket.ref() multiples times will have no additional effect.

        The socket.ref() method returns a reference to the socket so calls can be chained.

        默认情况下,绑定套接字会照成只要套接字打开,就会阻碍Node.js进程存活下去。socket.unref()函数是用来将套接字从保持Node.js进程活跃的引用计数器中排除。socket.ref()函数将套接字重新加回到引用计数器中,并恢复默认的行为。
        这是因为Node.js是单进程的缘故

        调用socket.ref()多次并不会有额外的影响。

        socket.ref()函数返回一个套接字的引用,因此调用可以被连接起来。

        socket.unref()

        Added in: v0.9.1
        By default, binding a socket will cause it to block the Node.js process from exiting as long as the socket is open. The socket.unref() method can be used to exclude the socket from the reference counting that keeps the Node.js process active, allowing the process to exit even if the socket is still listening.

        Calling socket.unref() multiple times will have no addition effect.

        The socket.unref() method returns a reference to the socket so calls can be chained.

        默认情况下,绑定套接字会照成只要套接字打开,就会阻碍Node.js进程存活下去。socket.unref()函数是用来将套接字从保持Node.js进程活跃的引用计数器中排除,允许即使进程退出,套机字也会依旧继续监听。
        这是因为Node.js是单进程的缘故

        调用socket.unref()多次并不会有额外的影响。

        socket.unref()函数返回一个套接字的引用,因此调用可以被连接起来。

        Change to asynchronous socket.bind() behavior

        As of Node.js v0.10, dgram.Socket#bind() changed to an asynchronous execution model. Legacy code that assumes synchronous behavior, as in the following example:

        从Node.js v0.10起,dgram.Socket#bind()方法就改为异步执行模式。遗留的代码假定还是同步行为,就像下面的例子:

        const s = dgram.createSocket('udp4');
        s.bind(1234);
        s.addMembership('224.0.0.114');

        Must be changed to pass a callback function to the dgram.Socket#bind() function:

        必须改为传递一个回调函数给dgram.Socket#bind()函数

        const s = dgram.createSocket('udp4');
        s.bind(1234, () => {
          s.addMembership('224.0.0.114');
        });

        dgram module functions

        dgram.createSocket(options[, callback])

        Added in: v0.11.13

        • options
        • callback Attached as a listener to ‘message’ events.
        • Returns:
        • Creates a dgram.Socket object. The options argument is an object that should contain a type field of either udp4 or udp6 and an optional boolean reuseAddr field.

          When reuseAddr is true socket.bind() will reuse the address, even if another process has already bound a socket on it. reuseAddr defaults to false. An optional callback function can be passed specified which is added as a listener for ‘message’ events.

          Once the socket is created, calling socket.bind() will instruct the socket to begin listening for datagram messages. When address and port are not passed to socket.bind() the method will bind the socket to the “all interfaces” address on a random port (it does the right thing for both udp4 and udp6 sockets). The bound address and port can be retrieved using socket.address().address and socket.address().port.

          • options
          • callback - 作为’message’ 事件的监听器。 可选参数
          • Returns:
          • 创建一个dgram.Socket对象。options参数是一个对象,它包含一个类型域,要么是udp4要么是udp6和一个可选的布尔类型的reuseAddr域。

            reuseAddr为真时,即使其它进程将已经将socket绑定在该地址上,socket.bind()也会重用该地址。reuseAddr默认是假。可以传递一个回调函数指定是否添加一个’message’事件的监听器。

            一旦套接字被创建,就会调用socket.bind(),然后通知套接字开始监听数据报文消息。当地址或者端口没有被传递给socket.bind(),该方法就会将套接字绑定到所有的接口地址使用一个随机的端口号(它对于udp4和udp6都是正确的)。绑定的地址和端口可以使用socket.address().addresssocket.address().port来检索。

            dgram.createSocket(type[, callback])

            Added in: v0.1.99

            • type - Either ‘udp4’ or ‘udp6’
            • callback - Attached as a listener to ‘message’ events. Optional
            • Returns:

            Creates a dgram.Socket object of the specified type. The type argument can be either udp4 or udp6. An optional callback function can be passed which is added as a listener for ‘message’ events.

            Once the socket is created, calling socket.bind() will instruct the socket to begin listening for datagram messages. When address and port are not passed to socket.bind() the method will bind the socket to the “all interfaces” address on a random port (it does the right thing for both udp4 and udp6 sockets). The bound address and port can be retrieved using socket.address().address and socket.address().port.

            • type - ‘udp4’ 或者 ‘udp6’
            • callback - 作为’message’ 事件的监听器。 可选参数
            • Returns:

            创建一个指定类型的dgram.Socket对象。type参数可以是udp4或者udp6。可以传递一个可选的回调函数作为’message’事件的监听器。

            一旦套接字被创建,就会调用socket.bind(),然后通知套接字开始监听数据报文消息。当地址或者端口没有被传递给socket.bind(),该方法就会将套接字绑定到所有的接口地址使用一个随机的端口号(它对于udp4和udp6都是正确的)。绑定的地址和端口可以使用socket.address().addresssocket.address().port来检索。

            你可能感兴趣的:(————,Node.js)