UDP 連接


1. UDP connect

我們經常說UDP是無連接的傳輸協議, 如果UDP調用connect呢? 會發生什么?
UDP套接字調用connect函數, 跟TCP連接調用connect不一樣: 沒有三次握手過程. 而且, 內核只是檢查是否存在立即可知的錯誤(e.g. 一個顯然不可達的目的地, 由於非法端口/ip地址等原因), 記錄對端的IP地址和端口號(取自傳遞給connect的套接字地址結構), 然后立即返回到調用進程.
用sockname是本地協議地址, peername是對端協議地址, 那么UDP connect(已連接UDP套接字)更好的名字是setpeername, UDP bind更好的名字是setsockname.

因此, UDP connect並不是在通信兩端之間真正建立了可靠連接, 而只是設置對端協議地址.

1.1 UDP連接的概念

  • 未連接UDP套接字(unconnected UDP socket), 新創建UDP套接字默認;
  • 已連接UDP套接字(connected UDP socket), 對UDP套接字調用connect的結果;

1.2 未連接UDP套接字 與 已連接UDP套接字

已連接UDP套接字在未連接UDP套接字 (默認)基礎上, 發生了變化:
1)不能給輸出操作指定目的IP地址和端口號. i.e. 不能使用sendto(傳入目的地址結構, 如果非要使用sendto, 地址結構參數必須為NULL), 而改用write或read. 因為寫已連接UDP套接字上的任何內容, 都自動發送到由connect指定的對端協議地址(IP地址+端口號);

TCP和UDP套接字: 可指定目的協議地址嗎?

套接字類型 write或send 不指定目的地址的
sendto
指定目的地址的
sendto
TCP套接字 可以 可以 EISCONN
UDP套接字, 已連接 可以 可以 EISCONN
UDP套接字, 未連接 EDESTADDRREQ EDESTADDRREQ 可以

2)不必使用recvfrom以獲取數據報的發送者, 改用read, recv或recvmsg.
缺點: 內核返回的數據報, 只有那些來自connect所指定對端協議地址的數據報. 也就是說, 接收到的數據報中, 如果源地址 != connect指定對端地址, 則進程不會接收到.

問題: 進程不收到的UDP報文, 會如何處理?
可能投遞到同一主機上的其他某個UDP套接字. 如果沒有相匹配的其他套接字, UDP將丟棄並生成相應的ICMP不可達錯誤.

3)由已連接UDP套接字引發的異步錯誤會返回給它們所在的進程, 而未連接UDP套接字不接收任何異步錯誤.

小結
UDP套接字何時調用connect?
當UDP客戶進程或服務器進程只使用自己的UDP套接字與確定的唯一對端進行通信時, 才調用connect. 調用connect的通常是UDP客戶, 少數情況下可能UDP服務器, 如UDP服務器與單個客戶長時間通信(TFTP).

1.2 多次調用connect

一個已連接UDP套接字的進程, 何時可以再次調用connect?

  1. 指定新的IP地址和端口號;
  2. 斷開套接字;

注意: 對於TCP套接字, 只能調用一次connect.

對於1), 類似於第一次調用connect方式, 為connect指定新的IP地址和端口號;
對於2), 再次調用connect時, 需要把套接字地址結構中的地址族成員(IPv4為sin_family, IPv6為sin6_family) 設置為AF_UNSPEC. 可能返回EAFNOSUPPORT錯誤, 不過沒關系, 忽略即可.
不同Unix變體可能有多種辦法斷開連接, 不過, 用AF_UNSPEC傳遞給connect的sa_family是最通用的方法.

而且, man connect(2)提到, 斷開套接字連接, 應該用AF_UNSPEC傳遞給connect的sa_family

Generally, connection-based protocol sockets may successfully connect() only once; connectionless
protocol sockets may use connect() multiple times to change their association. Connectionless
sockets may dissolve the association by connecting to an address with the sa_family member of
sockaddr set to AF_UNSPEC (supported on Linux since kernel 2.2).

1.3 性能

多次發送數據時, 已連接UDP套接字效率 > 未連接UDP套接字效率.

UNP 8.11.2提到, 臨時連接未連接的UDP套接字大約會耗費每個UDP傳輸三分之一的開銷.

以2次發送數據報為例,
未連接UDP套接字調用2次 sendto發送數據報, 然后斷開連接. 執行步驟:
1)連接套接字;
2)輸出第一個數據報;
3)斷開套接字連接;
4)連接套接字;
5)輸出第二個數據報;
6)斷開套接字連接;

內核復制2次IP地址+端口號

已連接UDP套接字調用1次connect連接, 2次write發送數據報. 執行步驟:
1)連接套接字;
2)輸出第一個數據報;
3)輸出第二個數據報;

內核復制1次IP地址+端口號


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM