概述
本文為 Winsock API 系列第三篇,詳細介紹 setsockopt 與 shutdown 兩個核心套接字控制函數,涵蓋語法、參數、返回值、可用選項及實戰說明,基於 Winsock 1.1 規範(1993 年 1 月 20 日發布)。
setsockopt - 設定 Socket 選項
函數原型
int PASCAL FAR setsockopt(
SOCKET s, // Socket 識別碼
int level, // 選項所在的協議層級
int optname, // 選項名稱
const char FAR *optval, // 選項值緩衝區
int optlen // 選項值長度
);
參數說明
| 參數 | 說明 |
s | 欲設定選項的 Socket 識別碼 |
level | 選項所在的協議層級(如 SOL_SOCKET, IPPROTO_TCP) |
optname | 要設定的具體選項名稱 |
optval | 指向包含選項值的緩衝區指標 |
optlen | optval 緩衝區的長度(位元組) |
返回值
- 成功:返回 0
- 失敗:返回
SOCKET_ERROR,調用 WSAGetLastError() 獲取具體錯誤碼
常用 Socket 選項 (SOL_SOCKET 層級)
| 選項常數 | 類型 | 說明 |
| SO_BROADCAST | BOOL | 允許發送廣播資料 |
| SO_DEBUG | BOOL | 啟用除錯資訊記錄(* 系統保留) |
| SO_DONTLINGER | BOOL | 關閉時不等待資料發送完成(與 SO_LINGER 互斥) |
| SO_DONTROUTE | BOOL | 資料不經路由直接發送(* 系統保留) |
| SO_KEEPALIVE | BOOL | 定期發送保活封包偵測連線狀態(* 系統保留) |
| SO_LINGER | struct linger* | 設定關閉行為:是否等待未傳送資料 |
| SO_OOBINLINE | BOOL | 帶外資料納入正常資料流接收 |
| SO_RCVBUF | int | 設定接收緩衝區大小(* 系統保留) |
| SO_REUSEADDR | BOOL | 允許重用本地位址與埠 |
| SO_SNDBUF | int | 設定發送緩衝區大小(* 系統保留) |
TCP 專用選項 (IPPROTO_TCP 層級)
| 選項常數 | 類型 | 說明 |
| TCP_NODELAY | BOOL | 停用 Nagle 演算法,立即發送小封包 |
> **註**:標註 * 的選項通常由系統內部管理,應用程式不建議直接修改。
shutdown - 停止 Socket 收發功能
函數原型
int PASCAL FAR shutdown(
SOCKET s, // Socket 識別碼
int how // 停止操作的標誌
);
參數說明
how 值 | 行為 |
| 0 | 停止接收:後續 recv 將返回 0(連線關閉),對方仍可發送 |
| 1 | 停止發送:後續 send 將失敗,對方接收到 FIN 封包 |
| 2 | 同時停止發送與接收(完全關閉) |
返回值
- 成功:返回 0
- 失敗:返回
SOCKET_ERROR,調用 WSAGetLastError() 獲取錯誤碼
關鍵差異:shutdown vs closesocket
shutdown 只停止指定方向的資料流,Socket 描述符仍有效,可用於實現「半關閉」協議
closesocket 完全釋放 Socket 資源,雙向通道同時關閉
- 典型用法:
shutdown(s, 1) 發送 FIN,接收對方 ACK 後再 closesocket
實戰建議
- 設定
SO_REUSEADDR 可避免「Address already in use」錯誤,適用於頻繁重啟的伺服器
- 高效能場景啟用
TCP_NODELAY 減少延遲,但會增加封包數量
- 優雅關閉連線:先
shutdown(s, 1),循環 recv 直到返回 0,最後 closesocket
- 所有失敗情況必須檢查
WSAGetLastError(),常見錯誤:WSAENOTSOCK、WSAEINVAL、WSAENOPROTOOPT