【網絡編程】TCPIP-8-套接字的多種選項



前言

說明:

  • demo 基於 Linux。

8. 套接字的多種選項

一般創建好套接字后直接使用即可,有些配置是默認的,當然也可以通過以下修改。

8.1 API getsockopt(); & setsockopt();

/*
sock: 用於查看選項套接字文件描述符
level: 要查看的可選項協議層
optname: 要查看的可選項名
optval: 保存查看結果的緩沖地址值
optlen: 向第四個參數傳遞的緩沖大小。調用函數候,該變量中保存通過第四個參數返回的可選項信息的字節數。
成功時返回 0 ,失敗時返回 -1
*/
#include <sys/socket.h>
int getsockopt(int sock, int level, int optname, void *optval, socklen_t *optlen);
/*
sock: 用於更改選項套接字文件描述符
level: 要更改的可選項協議層
optname: 要更改的可選項名
optval: 保存更改結果的緩沖地址值
optlen: 向第四個參數傳遞的緩沖大小。調用函數候,該變量中保存通過第四個參數返回的可選項信息的字節數。
成功時返回 0 ,失敗時返回 -1
*/
#include <sys/socket.h>
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);

8.2 套接字選項

注意,套接字可選項是分層的。

  • SOL_SOCKET:套接字的通用可選項。
  • IPPROTO_TCP:可選項是 TCP 協議的相關事項。
  • IPPROTO_IP:IP 協議相關事項。
協議層 選項名 讀取 設置
SOL_SOCKET SO_SNDBUF O O
SOL_SOCKET SO_RCVBUF O O
SOL_SOCKET SO_REUSEADDR O O
SOL_SOCKET SO_KEEPALIVE O O
SOL_SOCKET SO_BROADCAST O O
SOL_SOCKET SO_DONTROUTE O O
SOL_SOCKET SO_OOBINLINE O O
SOL_SOCKET SO_ERROR O X
SOL_SOCKET SO_TYPE O X
IPPROTO_IP IP_TOS O O
IPPROTO_IP IP_TTL O O
IPPROTO_IP IP_MULTICAST_TTL O O
IPPROTO_IP IP_MULTICAST_LOOP O O
IPPROTO_IP IP_MULTICAST_IF O O
IPPROTO_TCP TCP_KEEPALIVE O O
IPPROTO_TCP TCP_NODELAY O O
IPPROTO_TCP TCP_MAXSEG O O

8.3 緩沖區相關可選項

SO_SNDBUF & SO_RCVBUF

SO_SNDBUF

  • 輸出緩沖區相關的可選項。
  • 可用其讀取當前 I/O 大小,也可以更改緩沖區大小。

SO_RCVBUF

  • 輸入緩沖區相關的可選項。
  • 可用其讀取當前 I/O 大小,也可以更改緩沖區大小。

8.4 端口復用

主要用到 SO_REUSEADDR

先了解一些概念再介紹該選項。

8.4.1 time-wait 狀態

MSL:報文段最大生存時間,它是任何報文段被丟棄前在網絡內的最長時間。

time-wait 狀態一般為 2 個MSL。其原因:

  • 保證 TCP 協議的全雙工連接能夠可靠關閉。
  • 保證這次連接的重復數據段從網絡中消失。保證下次連接收到的數據報文段都是來自新連接的目標端。
  • 返回ACK最長為也給MSL,如果沒有到達對端,對端重發,到本端最大也要一個MSL,所以得2個MSL

若服務器先異常斷開,四次揮手后進入 time-wait 狀態(一般為幾分鍾),在 time-wait 狀態時,該端口還是被占用的。服務器重啟后不能正常使用該端口,會輸出「bind() error」消息。必須等待該端口被置為 close 狀態才能被正常使用。

但是有些情景下是不能接受的,若服務器異常重啟,那得等待幾分鍾才能正常使用。
解決:使用SO_REUSEADDR來解決。

8.4.2 SO_REUSEADDR使用

在套接字的可選項中更改 SO_REUSEADDR 的狀態。
適當調整該參數,可將 Time-wait 狀態下的套接字端口號重新分配給新的套接字。
SO_REUSEADDR 的默認值為 0。
這就意味着無法分配 Time-wait 狀態下的套接字端口號。
因此需要將這個值改成 1 。

參考:

option = TRUE;
setsockopt(serv_sock, SOL_SOCKET, SO_REUSEADDR, (void *)&option, sizeof(option));

8.4.3 SO_REUSEADDR 作用

SO_REUSEADDR 作用:

  1. 當有一個有相同本地地址和端口的socket1處於TIME_WAIT狀態時,而你啟動的程序的socket2要占用該地址和端口,你的程序就要用到該選項。
  2. SO_REUSEADDR允許同一port上啟動同一服務器的多個實例(多個進程)。但每個實例綁定的IP地址是不能相同的。在有多塊網卡或用IP Alias技術的機器可以測試這種情況。
  3. SO_REUSEADDR允許單個進程綁定相同的端口到多個socket上,但每個socket綁定的ip地址不同。這和2很相似,區別請看UNPv1。
  4. SO_REUSEADDR允許完全相同的地址和端口的重復綁定。但這只用於UDP的多播,不用於TCP。

8.5 Nagle 算法

主要用到 TCP_NODELAY

Nagle 算法

  • 應用於 TCP 層。
  • TCP 套接字默認使用 Nagle 算法交換數據。
  • 算法:只有接收到前一數據的 ACK 消息, Nagle 算法才發送下一數據。

禁用

opt_val = 1;
setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt_val, sizeof(opt_val));

查看

getsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (void *)&opt_val, sizeof(opt_val));

參考


免責聲明!

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



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