首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

TCP/IP Winsock 同步阻塞模式程式設計關鍵技巧總結

     編輯:VC 教學

為什麼選擇同步 + 多執行緒?

同步邏輯清晰,專注業務邏輯;在搶佔式多任務 OS(WinNT/2K/XP)上配合多執行緒,效能可媲美非同步模型,且除錯容易。

七大關鍵技巧

1. 關閉 Nagle 演算法 —— 降低小封包延遲


int bNoDelay = 1;
setsockopt(sConnect, IPPROTO_TCP, TCP_NODELAY, (char*)&bNoDelay, sizeof(bNoDelay));

預設開啟 Nagle 會緩衝小封包,關閉後每次 send 立即發送,適合即時控制、工控系統。

2. 控制發送大小 —— 避免應用層斷幀

  • TCP MSS 預設 1460 位元組(MTU 1500 - IP/UDP 頭)。
  • 單次 send ≤ 1400 位元組,確保單一封包傳輸,接收端無需斷幀處理。
  • 不建議修改登錄檔調整 MSS,Microsoft 認為 1460 為最佳平衡點。

3. 縮短 connect 阻塞時間 —— 斷網偵測

同步 connect 斷網阻塞約 20 秒,兩種預檢方案:

方法阻塞時間備註
gethostbyaddr~4 秒解析 IP 至主機名,失敗即斷網
Ping (ICMP)~2 秒需發送原始封包,權限較高

// gethostbyaddr 範例
sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("192.168.1.3");
HOSTENT* pHost = gethostbyaddr((char*)&addr.sin_addr.s_addr, 4, AF_INET);
if (!pHost) { /* 斷網或 DNS 失敗 */ }

4. 解決 recv/send 阻塞 —— select 多工偵測


// 檢查可讀
TIMEVAL tv = {0, 1}; // 1ms timeout
FD_SET fds = {1, sConnect};
int ret = select(0, &fds, NULL, NULL, &tv);
if (ret == SOCKET_ERROR) { /* 錯誤 */ }
else if (ret == 0) { /* 超時,無資料 */ }
else { /* 可讀,呼叫 recv */ }

// 檢查可寫
FD_SET fds = {1, sConnect};
ret = select(0, NULL, &fds, NULL, &tv);
// 同理判斷

非同步選擇模型核心:先 select 再 recv/send,避免無限期阻塞。

5. 調整收發緩衝區大小


int bufSize = 20 * 1024; // 20KB
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&bufSize, sizeof(bufSize));
setsockopt(s, SOL_SOCKET, SO_RCVBUF, (char*)&bufSize, sizeof(bufSize));
// 驗證實際生效值
int actual = 0; int len = sizeof(actual);
getsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&actual, &len);

系統預設 8192,大量傳輸時可適度調大。

6. 伺服器多 IP 綁定同一埠


sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(3024);
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 綁定所有介面
bind(s, (sockaddr*)&addr, sizeof(addr));
listen(s, 10);

INADDR_ANY 讓伺服器同時監聽所有網卡 IP 的指定埠。

7. 變種 Client/Server 架構 —— 連線建立後雙向主動

  • 傳統:Client 請求 → Server 回應(半雙工)。
  • 變種:連線建立後,雙方均可主動推送資料(全雙工),適合 RTDB、SCADA、即時監控系統。
  • 實作要點:雙邊均以 接收優先循環 + 適時發送,配合 select 多工。

總結檢查清單

  • ☑ 關閉 TCP_NODELAY
  • ☑ 發送封包 ≤ 1400 位元組
  • ☑ connect 前以 gethostbyaddr/Ping 預檢
  • ☑ 所有 recv/send 前呼叫 select
  • ☑ 依負載調整 SO_SNDBUF/SO_RCVBUF
  • ☑ 伺服器使用 INADDR_ANY 多網卡支援
  • ☑ 採用雙向主動架構降低輪詢開銷
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved