Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[v10.x backport] dgram: add support for UDP connected sockets #30480

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 72 additions & 3 deletions doc/api/dgram.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,14 @@ added: 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.

### Event: 'connect'
<!-- YAML
added: REPLACEME
-->

The `'connect'` event is emitted after a socket is associated to a remote
address as a result of a successful [`connect()`][] call.

### Event: 'error'
<!-- YAML
added: v0.1.99
Expand Down Expand Up @@ -231,6 +239,34 @@ added: 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.

### socket.connect(port[, address][, callback])
<!-- YAML
added: REPLACEME
-->

* `port` {integer}
* `address` {string}
* `callback` {Function} Called when the connection is completed or on error.

Associates the `dgram.Socket` to a remote address and port. Every
message sent by this handle is automatically sent to that destination. Also,
the socket will only receive messages from that remote peer.
Trying to call `connect()` on an already connected socket will result
in an [`ERR_SOCKET_DGRAM_IS_CONNECTED`][] exception. If `address` is not
provided, `'127.0.0.1'` (for `udp4` sockets) or `'::1'` (for `udp6` sockets)
will be used by default. Once the connection is complete, a `'connect'` event
is emitted and the optional `callback` function is called. In case of failure,
the `callback` is called or, failing this, an `'error'` event is emitted.

### socket.disconnect()
<!-- YAML
added: REPLACEME
-->

A synchronous function that disassociates a connected `dgram.Socket` from
its remote address. Trying to call `disconnect()` on an already disconnected
socket will result in an [`ERR_SOCKET_DGRAM_NOT_CONNECTED`][] exception.

### socket.dropMembership(multicastAddress[, multicastInterface])
<!-- YAML
added: v0.6.9
Expand Down Expand Up @@ -277,7 +313,18 @@ 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.

### socket.send(msg[, offset, length], port[, address][, callback])
### socket.remoteAddress()
<!-- YAML
added: REPLACEME
-->

* Returns: {Object}

Returns an object containing the `address`, `family`, and `port` of the remote
endpoint. It throws an [`ERR_SOCKET_DGRAM_NOT_CONNECTED`][] exception if the
socket is not connected.

### socket.send(msg[, offset, length][, port][, address][, callback])
<!-- YAML
added: v0.1.99
changes:
Expand All @@ -295,6 +342,9 @@ changes:
pr-url: https://github.com/nodejs/node/pull/4374
description: The `msg` parameter can be an array now. Also, the `offset`
and `length` parameters are optional now.
- version: REPLACEME
pr-url: https://github.com/nodejs/node/pull/26871
description: Added support for sending data on connected sockets.
-->

* `msg` {Buffer|Uint8Array|string|Array} Message to be sent.
Expand All @@ -304,8 +354,10 @@ changes:
* `address` {string} Destination hostname or IP address.
* `callback` {Function} Called when the message has been sent.

Broadcasts a datagram on the socket. The destination `port` and `address` must
be specified.
Broadcasts a datagram on the socket.
For connectionless sockets, the destination `port` and `address` must be
specified. Connected sockets, on the other hand, will use their associated
remote endpoint, so the `port` and `address` arguments must not be set.

The `msg` argument contains the message to be sent.
Depending on its type, different behavior can apply. If `msg` is a `Buffer`
Expand Down Expand Up @@ -369,6 +421,20 @@ application and operating system. It is important to run benchmarks to
determine the optimal strategy on a case-by-case basis. Generally speaking,
however, sending multiple buffers is faster.

Example of sending a UDP packet using a socket connected to a port on
`localhost`:

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

**A Note about UDP datagram size**

The maximum size of an `IPv4/v6` datagram depends on the `MTU`
Expand Down Expand Up @@ -639,10 +705,13 @@ and `udp6` sockets). The bound address and port can be retrieved using

[`'close'`]: #dgram_event_close
[`Error`]: errors.html#errors_class_error
[`ERR_SOCKET_DGRAM_IS_CONNECTED`]: errors.html#errors_err_socket_dgram_is_connected
[`ERR_SOCKET_DGRAM_NOT_CONNECTED`]: errors.html#errors_err_socket_dgram_not_connected
[`EventEmitter`]: events.html
[`System Error`]: errors.html#errors_class_systemerror
[`close()`]: #dgram_socket_close_callback
[`cluster`]: cluster.html
[`connect()`]: #dgram_socket_connect_port_address_callback
[`dgram.Socket#bind()`]: #dgram_socket_bind_options_callback
[`dgram.createSocket()`]: #dgram_dgram_createsocket_options_callback
[`dns.lookup()`]: dns.html#dns_dns_lookup_hostname_options_callback
Expand Down
14 changes: 14 additions & 0 deletions doc/api/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -1571,6 +1571,17 @@ Data could be sent on a socket.

An attempt was made to operate on an already closed socket.

<a id="ERR_SOCKET_DGRAM_IS_CONNECTED"></a>
### ERR_SOCKET_DGRAM_IS_CONNECTED

A [`dgram.connect()`][] call was made on an already connected socket.

<a id="ERR_SOCKET_DGRAM_NOT_CONNECTED"></a>
### ERR_SOCKET_DGRAM_NOT_CONNECTED

A [`dgram.disconnect()`][] or [`dgram.remoteAddress()`][] call was made on a
disconnected socket.

<a id="ERR_SOCKET_DGRAM_NOT_RUNNING"></a>
### ERR_SOCKET_DGRAM_NOT_RUNNING

Expand Down Expand Up @@ -2140,7 +2151,10 @@ size.
[`crypto.scrypt()`]: crypto.html#crypto_crypto_scrypt_password_salt_keylen_options_callback
[`crypto.scryptSync()`]: crypto.html#crypto_crypto_scryptsync_password_salt_keylen_options
[`crypto.timingSafeEqual()`]: crypto.html#crypto_crypto_timingsafeequal_a_b
[`dgram.connect()`]: dgram.html#dgram_socket_connect_port_address_callback
[`dgram.createSocket()`]: dgram.html#dgram_dgram_createsocket_options_callback
[`dgram.disconnect()`]: dgram.html#dgram_socket_disconnect
[`dgram.remoteAddress()`]: dgram.html#dgram_socket_remoteaddress
[`errno`(3) man page]: http://man7.org/linux/man-pages/man3/errno.3.html
[`fs.readFileSync`]: fs.html#fs_fs_readfilesync_path_options
[`fs.readdir`]: fs.html#fs_fs_readdir_path_options_callback
Expand Down
Loading