UDP/資料報套接字#

穩定性:2 - 穩定

原始碼: lib/dgram.js

node:dgram 模組提供了 UDP 資料報套接字的實現。

import dgram from 'node:dgram';

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

server.on('error', (err) => {
  console.error(`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', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(41234);
// Prints: server listening 0.0.0.0:41234const dgram = require('node:dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.error(`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', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

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

類:dgram.Socket#

封裝了資料報的功能。

dgram.Socket 的新例項是使用 dgram.createSocket() 建立的。不應使用 new 關鍵字來建立 dgram.Socket 例項。

事件:'close'#

當套接字透過 close() 關閉後,會觸發 'close' 事件。一旦觸發,此套接字上將不會再觸發新的 'message' 事件。

事件:'connect'#

成功呼叫 connect() 後,套接字與遠端地址關聯時會觸發 'connect' 事件。

事件:'error'#

每當發生任何錯誤時,都會觸發 'error' 事件。事件處理函式會接收一個 Error 物件作為引數。

事件:'listening'#

一旦 dgram.Socket 可定址並可以接收資料,就會觸發 'listening' 事件。這可以是透過 socket.bind() 顯式觸發,也可以是在首次使用 socket.send() 傳送資料時隱式觸發。在 dgram.Socket 處於監聽狀態之前,底層的系統資源不存在,呼叫諸如 socket.address()socket.setTTL() 等方法將會失敗。

事件:'message'#

當套接字上有新的資料報可用時,會觸發 'message' 事件。事件處理函式會接收兩個引數:msgrinfo

如果傳入資料包的源地址是 IPv6 鏈路本地地址,則介面名稱會附加到 address 上。例如,在 en0 介面上收到的資料包,其地址欄位可能被設定為 'fe80::2618:1234:ab11:3b9c%en0',其中 '%en0' 是作為區域 ID 字尾的介面名稱。

socket.addMembership(multicastAddress[, multicastInterface])#

通知核心使用 IP_ADD_MEMBERSHIP 套接字選項,在給定的 multicastAddressmulticastInterface 上加入一個多播組。如果未指定 multicastInterface 引數,作業系統將選擇一個介面並向其新增成員關係。要向每個可用介面新增成員關係,需要多次呼叫 addMembership,每個介面呼叫一次。

在未繫結的套接字上呼叫此方法時,它將隱式繫結到一個隨機埠,並監聽所有介面。

當在多個 cluster 工作程序間共享一個 UDP 套接字時,socket.addMembership() 函式必須只調用一次,否則會發生 EADDRINUSE 錯誤。

import cluster from 'node:cluster';
import dgram from 'node:dgram';

if (cluster.isPrimary) {
  cluster.fork(); // Works ok.
  cluster.fork(); // Fails with EADDRINUSE.
} else {
  const s = dgram.createSocket('udp4');
  s.bind(1234, () => {
    s.addMembership('224.0.0.114');
  });
}const cluster = require('node:cluster');
const dgram = require('node:dgram');

if (cluster.isPrimary) {
  cluster.fork(); // Works ok.
  cluster.fork(); // Fails with EADDRINUSE.
} else {
  const s = dgram.createSocket('udp4');
  s.bind(1234, () => {
    s.addMembership('224.0.0.114');
  });
}

socket.addSourceSpecificMembership(sourceAddress, groupAddress[, multicastInterface])#

通知核心使用 IP_ADD_SOURCE_MEMBERSHIP 套接字選項,在給定的 sourceAddressgroupAddress 上加入一個特定源的多播頻道,使用 multicastInterface。如果未指定 multicastInterface 引數,作業系統將選擇一個介面並向其新增成員關係。要向每個可用介面新增成員關係,需要多次呼叫 socket.addSourceSpecificMembership(),每個介面呼叫一次。

在未繫結的套接字上呼叫此方法時,它將隱式繫結到一個隨機埠,並監聽所有介面。

socket.address()#

返回一個包含套接字地址資訊的物件。對於 UDP 套接字,此物件將包含 addressfamilyport 屬性。

如果在未繫結的套接字上呼叫此方法,將丟擲 EBADF 錯誤。

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

對於 UDP 套接字,使 dgram.Socket 在一個指定的 port 和可選的 address 上監聽資料報訊息。如果未指定 portport0,作業系統將嘗試繫結到一個隨機埠。如果未指定 address,作業系統將嘗試監聽所有地址。繫結完成後,會觸發一個 'listening' 事件,並呼叫可選的 callback 函式。

同時指定一個 'listening' 事件監聽器並向 socket.bind() 方法傳遞一個 callback 是無害的,但沒有太大用處。

一個已繫結的資料報套接字會使 Node.js 程序保持執行以接收資料報訊息。

如果繫結失敗,會產生一個 'error' 事件。在極少數情況下(例如,嘗試繫結一個已關閉的套接字),可能會丟擲一個 Error

一個在 41234 埠監聽的 UDP 伺服器示例

import dgram from 'node:dgram';

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

server.on('error', (err) => {
  console.error(`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', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

server.bind(41234);
// Prints: server listening 0.0.0.0:41234const dgram = require('node:dgram');
const server = dgram.createSocket('udp4');

server.on('error', (err) => {
  console.error(`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', () => {
  const address = server.address();
  console.log(`server listening ${address.address}:${address.port}`);
});

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

socket.bind(options[, callback])#

對於 UDP 套接字,使 dgram.Socket 在一個指定的 port 和可選的 address 上監聽資料報訊息,這些引數作為第一個引數 options 物件的屬性傳入。如果未指定 portport0,作業系統將嘗試繫結到一個隨機埠。如果未指定 address,作業系統將嘗試監聽所有地址。繫結完成後,會觸發一個 'listening' 事件,並呼叫可選的 callback 函式。

options 物件可能包含一個 fd 屬性。當設定了一個大於 0fd 時,它將包裝一個具有給定檔案描述符的現有套接字。在這種情況下,portaddress 的屬性將被忽略。

同時指定一個 'listening' 事件監聽器並向 socket.bind() 方法傳遞一個 callback 是無害的,但沒有太大用處。

當與 cluster 模組一起使用 dgram.Socket 物件時,options 物件可能包含一個額外的 exclusive 屬性。當 exclusive 設定為 false(預設值)時,叢集工作程序將使用相同的底層套接字控制代碼,從而允許共享連線處理職責。然而,當 exclusivetrue 時,控制代碼不被共享,嘗試共享埠會導致錯誤。建立 dgram.Socket 時,如果將 reusePort 選項設定為 true,那麼在呼叫 socket.bind()exclusive 將始終為 true

一個已繫結的資料報套接字會使 Node.js 程序保持執行以接收資料報訊息。

如果繫結失敗,會產生一個 'error' 事件。在極少數情況下(例如,嘗試繫結一個已關閉的套接字),可能會丟擲一個 Error

下面顯示了一個在獨佔埠上監聽的套接字示例。

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

socket.close([callback])#

  • callback <Function> 當套接字關閉時呼叫。

關閉底層套接字並停止在其上監聽資料。如果提供了回撥函式,它將被新增為 'close' 事件的監聽器。

socket[Symbol.asyncDispose]()#

呼叫 socket.close() 並返回一個在套接字關閉時履行的 Promise。

socket.connect(port[, address][, callback])#

dgram.Socket 與遠端地址和埠關聯。此控制代碼傳送的每條訊息都會自動傳送到該目標。此外,套接字將只接收來自該遠端對等方的訊息。嘗試在已連線的套接字上呼叫 connect() 將導致 ERR_SOCKET_DGRAM_IS_CONNECTED 異常。如果未提供 address,則預設使用 '127.0.0.1'(對於 udp4 套接字)或 '::1'(對於 udp6 套接字)。連線完成後,會觸發一個 'connect' 事件,並呼叫可選的 callback 函式。如果失敗,則呼叫 callback,或者,如果沒有 callback,則觸發一個 'error' 事件。

socket.disconnect()#

一個同步函式,用於解除已連線的 dgram.Socket 與其遠端地址的關聯。嘗試在未繫結或已斷開連線的套接字上呼叫 disconnect() 將導致 ERR_SOCKET_DGRAM_NOT_CONNECTED 異常。

socket.dropMembership(multicastAddress[, multicastInterface])#

指示核心使用 IP_DROP_MEMBERSHIP 套接字選項離開位於 multicastAddress 的多播組。當套接字關閉或程序終止時,核心會自動呼叫此方法,因此大多數應用程式永遠沒有理由呼叫此方法。

如果未指定 multicastInterface,作業系統將嘗試在所有有效介面上退出成員關係。

socket.dropSourceSpecificMembership(sourceAddress, groupAddress[, multicastInterface])#

指示核心使用 IP_DROP_SOURCE_MEMBERSHIP 套接字選項離開位於給定 sourceAddressgroupAddress 的特定源多播頻道。當套接字關閉或程序終止時,核心會自動呼叫此方法,因此大多數應用程式永遠沒有理由呼叫此方法。

如果未指定 multicastInterface,作業系統將嘗試在所有有效介面上退出成員關係。

socket.getRecvBufferSize()#

  • 返回:<number> SO_RCVBUF 套接字接收緩衝區的大小(以位元組為單位)。

如果在未繫結的套接字上呼叫此方法,將丟擲 ERR_SOCKET_BUFFER_SIZE 錯誤。

socket.getSendBufferSize()#

  • 返回:<number> SO_SNDBUF 套接字傳送緩衝區的大小(以位元組為單位)。

如果在未繫結的套接字上呼叫此方法,將丟擲 ERR_SOCKET_BUFFER_SIZE 錯誤。

socket.getSendQueueSize()#

  • 返回:<number> 排隊等待發送的位元組數。

socket.getSendQueueCount()#

  • 返回:<number> 當前在佇列中等待處理的傳送請求數量。

socket.ref()#

預設情況下,繫結一個套接字會阻止 Node.js 程序退出,只要該套接字是開啟的。socket.unref() 方法可用於將套接字從保持 Node.js 程序活動的引用計數中排除。socket.ref() 方法將套接字重新添加回引用計數,並恢復預設行為。

多次呼叫 socket.ref() 不會產生額外效果。

socket.ref() 方法返回對套接字的引用,因此可以進行鏈式呼叫。

socket.remoteAddress()#

返回一個包含遠端端點的 addressfamilyport 的物件。如果套接字未連線,此方法將丟擲 ERR_SOCKET_DGRAM_NOT_CONNECTED 異常。

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

在套接字上廣播一個數據報。對於無連線的套接字,必須指定目標 portaddress。而對於已連線的套接字,它們將使用其關聯的遠端端點,因此不得設定 portaddress 引數。

msg 引數包含要傳送的訊息。根據其型別,可能會有不同的行為。如果 msg 是一個 Buffer、任何 TypedArrayDataView,那麼 offsetlength 分別指定了訊息在 Buffer 中的起始偏移量和訊息的位元組數。如果 msg 是一個 String,那麼它會自動轉換為使用 'utf8' 編碼的 Buffer。對於包含多位元組字元的訊息,offsetlength 將根據位元組長度而不是字元位置來計算。如果 msg 是一個數組,則不能指定 offsetlength

address 引數是一個字串。如果 address 的值是一個主機名,將使用 DNS 來解析該主機的地址。如果未提供 address 或其為 nullish,則預設使用 '127.0.0.1'(對於 udp4 套接字)或 '::1'(對於 udp6 套接字)。

如果套接字之前沒有透過呼叫 bind 進行繫結,那麼套接字將被分配一個隨機的埠號,並繫結到“所有介面”地址(udp4 套接字為 '0.0.0.0'udp6 套接字為 '::0')。

可以指定一個可選的 callback 函式,用於報告 DNS 錯誤或確定何時可以安全地重用 buf 物件。DNS 查詢會使傳送時間延遲至少一個 Node.js 事件迴圈的 tick。

唯一能確定資料報已傳送的方法是使用 callback。如果發生錯誤並且提供了 callback,錯誤將作為第一個引數傳遞給 callback。如果沒有提供 callback,錯誤將作為 'error' 事件在 socket 物件上觸發。

偏移量和長度是可選的,但如果使用其中任何一個,則兩者都必須設定。它們僅在第一個引數是 BufferTypedArrayDataView 時才受支援。

如果在未繫結的套接字上呼叫此方法,將丟擲 ERR_SOCKET_BAD_PORT 錯誤。

傳送 UDP 包到 localhost 上某個埠的示例:

import dgram from 'node:dgram';
import { Buffer } from 'node:buffer';

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

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

將由多個緩衝區組成的 UDP 包傳送到 127.0.0.1 上的某個埠的示例:

import dgram from 'node:dgram';
import { Buffer } from 'node:buffer';

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

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

傳送多個緩衝區的速度可能會更快或更慢,具體取決於應用程式和作業系統。應透過基準測試來逐案確定最佳策略。然而,一般來說,傳送多個緩衝區會更快。

使用連線到 localhost 某個埠的套接字傳送 UDP 包的示例

import dgram from 'node:dgram';
import { Buffer } from 'node:buffer';

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

const message = Buffer.from('Some bytes');
const client = dgram.createSocket('udp4');
client.connect(41234, 'localhost', (err) => {
  client.send(message, (err) => {
    client.close();
  });
});
關於 UDP 資料報大小的說明#

IPv4/v6 資料報的最大大小取決於 MTU(最大傳輸單元)和 Payload Length 欄位的大小。

  • Payload Length 欄位是 16 位寬,這意味著一個正常的有效載荷不能超過 64K 八位位元組,包括網際網路頭部和資料(65,507 位元組 = 65,535 − 8 位元組 UDP 頭部 − 20 位元組 IP 頭部);這通常適用於迴環介面,但對於大多數主機和網路來說,如此長的資料報訊息是不切實際的。

  • MTU 是給定的鏈路層技術可以支援的資料報訊息的最大尺寸。對於任何鏈路,IPv4 規定了最小 MTU 為 68 個八位位元組,而 IPv4 推薦的 MTU 是 576(通常推薦作為撥號類應用的 MTU),無論它們是完整到達還是分片到達。

    對於 IPv6,最小 MTU 是 1280 個八位位元組。然而,強制的最小分片重組緩衝區大小是 1500 個八位位元組。68 個八位位元組的值非常小,因為大多數當前的鏈路層技術,如乙太網,其最小 MTU 為 1500。

無法預先知道一個數據包可能經過的每個鏈路的 MTU。傳送大於接收方 MTU 的資料報將不會成功,因為資料包會被靜默丟棄,而不會通知源端資料未到達其預定接收者。

socket.setBroadcast(flag)#

設定或清除 SO_BROADCAST 套接字選項。當設定為 true 時,UDP 包可以傳送到本地介面的廣播地址。

如果在未繫結的套接字上呼叫此方法,將丟擲 EBADF 錯誤。

socket.setMulticastInterface(multicastInterface)#

本節中所有對 scope 的引用都指的是 IPv6 區域索引,該索引由 RFC 4007 定義。在字串形式中,帶有 scope 索引的 IP 寫作 'IP%scope',其中 scope 是介面名稱或介面編號。

將套接字的默認出站多播介面設定為所選介面,或恢復為系統介面選擇。multicastInterface 必須是套接字族中一個 IP 的有效字串表示。

對於 IPv4 套接字,這應該是為所需物理介面配置的 IP。所有在套接字上傳送到多播地址的資料包都將透過最近一次成功呼叫此方法所確定的介面傳送。

對於 IPv6 套接字,multicastInterface 應包含一個 scope 來指示介面,如下例所示。在 IPv6 中,單個 send 呼叫也可以在地址中使用顯式 scope,因此只有傳送到未指定顯式 scope 的多播地址的資料包才會受到最近一次成功呼叫此方法的影響。

如果在未繫結的套接字上呼叫此方法,將丟擲 EBADF 錯誤。

示例:IPv6 出站多播介面#

在大多數系統中,scope 格式使用介面名稱

const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
  socket.setMulticastInterface('::%eth1');
}); 

在 Windows 上,scope 格式使用介面編號

const socket = dgram.createSocket('udp6');

socket.bind(1234, () => {
  socket.setMulticastInterface('::%2');
}); 
示例:IPv4 出站多播介面#

所有系統都使用所需物理介面上主機的 IP

const socket = dgram.createSocket('udp4');

socket.bind(1234, () => {
  socket.setMulticastInterface('10.0.0.2');
}); 
呼叫結果#

在未準備好傳送或已不再開啟的套接字上呼叫,可能會丟擲“Not running”Error

如果 multicastInterface 無法被解析為 IP,則會丟擲“EINVAL”System Error

在 IPv4 上,如果 multicastInterface 是一個有效的地址但與任何介面都不匹配,或者地址與族不匹配,則會丟擲像 EADDRNOTAVAILEPROTONOSUP 這樣的System Error

在 IPv6 上,大多數指定或省略 scope 的錯誤將導致套接字繼續使用(或返回到)系統的預設介面選擇。

套接字地址族的任意地址(IPv4 的 '0.0.0.0' 或 IPv6 的 '::')可用於將套接字默認出站介面的控制權交還給系統,以用於未來的多播資料包。

socket.setMulticastLoopback(flag)#

設定或清除 IP_MULTICAST_LOOP 套接字選項。當設定為 true 時,多播資料包也將在本地介面上接收。

如果在未繫結的套接字上呼叫此方法,將丟擲 EBADF 錯誤。

socket.setMulticastTTL(ttl)#

設定 IP_MULTICAST_TTL 套接字選項。雖然 TTL 通常代表“生存時間”(Time to Live),但在這種情況下,它指定了資料包允許經過的 IP 跳數,特別適用於多播流量。每個轉發資料包的路由器或閘道器都會將 TTL 減一。如果 TTL 被路由器減為 0,資料包將不會被轉發。

ttl 引數的值可以在 0 到 255 之間。大多數系統上的預設值是 1

如果在未繫結的套接字上呼叫此方法,將丟擲 EBADF 錯誤。

socket.setRecvBufferSize(size)#

設定 SO_RCVBUF 套接字選項。設定套接字最大接收緩衝區的大小(以位元組為單位)。

如果在未繫結的套接字上呼叫此方法,將丟擲 ERR_SOCKET_BUFFER_SIZE 錯誤。

socket.setSendBufferSize(size)#

設定 SO_SNDBUF 套接字選項。設定套接字最大發送緩衝區的大小(以位元組為單位)。

如果在未繫結的套接字上呼叫此方法,將丟擲 ERR_SOCKET_BUFFER_SIZE 錯誤。

socket.setTTL(ttl)#

設定 IP_TTL 套接字選項。雖然 TTL 通常代表“生存時間”(Time to Live),但在這種情況下,它指定了資料包允許經過的 IP 跳數。每個轉發資料包的路由器或閘道器都會將 TTL 減一。如果 TTL 被路由器減為 0,資料包將不會被轉發。更改 TTL 值通常用於網路探測或進行多播。

ttl 引數的值可以在 1 到 255 之間。大多數系統上的預設值是 64。

如果在未繫結的套接字上呼叫此方法,將丟擲 EBADF 錯誤。

socket.unref()#

預設情況下,繫結一個套接字會阻止 Node.js 程序退出,只要該套接字是開啟的。socket.unref() 方法可用於將套接字從保持 Node.js 程序活動的引用計數中排除,從而允許程序在套接字仍在監聽時退出。

多次呼叫 socket.unref() 不會產生額外效果。

socket.unref() 方法返回對套接字的引用,因此可以進行鏈式呼叫。

node:dgram 模組函式#

dgram.createSocket(options[, callback])#

  • options <Object> 可用選項包括:
    • type <string> 套接字族。必須是 'udp4''udp6'。必需。
    • reuseAddr <boolean> 當為 true 時,socket.bind() 將重用地址,即使另一個程序已經綁定了該地址上的套接字,但只有一個套接字可以接收資料。預設值: false
    • reusePort <boolean> 當為 true 時,socket.bind() 將重用埠,即使另一個程序已經綁定了該埠上的套接字。傳入的資料報將被分發到監聽的套接字。此選項僅在某些平臺上可用,例如 Linux 3.9+、DragonFlyBSD 3.6+、FreeBSD 12.0+、Solaris 11.4 和 AIX 7.2.5+。在不支援的平臺上,當套接字被繫結時,此選項會引發錯誤。預設值: false
    • ipv6Only <boolean>ipv6Only 設定為 true 將停用雙棧支援,即繫結到地址 :: 不會使 0.0.0.0 被繫結。預設值: false
    • recvBufferSize <number> 設定 SO_RCVBUF 套接字值。
    • sendBufferSize <number> 設定 SO_SNDBUF 套接字值。
    • lookup <Function> 自定義查詢函式。預設值: dns.lookup()
    • signal <AbortSignal> 一個可用於關閉套接字的 AbortSignal。
    • receiveBlockList <net.BlockList> receiveBlockList 可用於丟棄發往特定 IP 地址、IP 範圍或 IP 子網的入站資料報。如果伺服器位於反向代理、NAT 等之後,此功能將不起作用,因為與阻止列表進行檢查的地址是代理的地址,或 NAT 指定的地址。
    • sendBlockList <net.BlockList> sendBlockList 可用於停用對特定 IP 地址、IP 範圍或 IP 子網的出站訪問。
  • callback <Function> 作為 'message' 事件的監聽器附加。可選。
  • 返回:<dgram.Socket>

建立一個 dgram.Socket 物件。套接字建立後,呼叫 socket.bind() 將指示套接字開始監聽資料報訊息。當未向 socket.bind() 傳遞 addressport 時,該方法會將套接字繫結到“所有介面”地址的一個隨機埠(對於 udp4udp6 套接字都能正確處理)。可以使用 socket.address().addresssocket.address().port 來檢索繫結的地址和埠。

如果啟用了 signal 選項,在相應的 AbortController 上呼叫 .abort() 類似於在套接字上呼叫 .close()

const controller = new AbortController();
const { signal } = controller;
const server = dgram.createSocket({ type: 'udp4', signal });
server.on('message', (msg, rinfo) => {
  console.log(`server got: ${msg} from ${rinfo.address}:${rinfo.port}`);
});
// Later, when you want to close the server.
controller.abort(); 

dgram.createSocket(type[, callback])#

建立一個指定 typedgram.Socket 物件。

套接字建立後,呼叫 socket.bind() 將指示套接字開始監聽資料報訊息。當未向 socket.bind() 傳遞 addressport 時,該方法會將套接字繫結到“所有介面”地址的一個隨機埠(對於 udp4udp6 套接字都能正確處理)。可以使用 socket.address().addresssocket.address().port 來檢索繫結的地址和埠。