同步邏輯清晰,專注業務邏輯;在搶佔式多任務 OS(WinNT/2K/XP)上配合多執行緒,效能可媲美非同步模型,且除錯容易。
int bNoDelay = 1;
setsockopt(sConnect, IPPROTO_TCP, TCP_NODELAY, (char*)&bNoDelay, sizeof(bNoDelay));
預設開啟 Nagle 會緩衝小封包,關閉後每次 send 立即發送,適合即時控制、工控系統。
send ≤ 1400 位元組,確保單一封包傳輸,接收端無需斷幀處理。同步 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 失敗 */ }
// 檢查可讀
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,避免無限期阻塞。
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,大量傳輸時可適度調大。
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 的指定埠。
select 多工。