Socket 是網絡通信的基石。本文系統梳理 **Client/Server 模型**、**核心 Socket API**、**連接建立/數據傳輸/關閉的時序流程**,並對比**面向連接 (TCP)** 與**無連接 (UDP)** 的調用差異,為 Windows 平台網絡編程提供清晰的 API 速查與原理參考。
TCP/IP 網絡中進程間通信遵循 **非對等、異步** 的 Client/Server 模式:
socket() 創建套接字bind() 綁定本地 IP/端口 (Well-known Port)listen() 監聽,內核維護「已完成連接隊列」與「未完成連接隊列」accept() 從已完成隊列取出連接,**返回新套接字** 用於具體通信,原套接字繼續監聽recv()/send() 處理業務closesocket() 關閉連接套接字socket() 創建套接字connect() 主動發起三次握手連接服務器 IP/端口send()/recv() 交換數據closesocket() 關閉套接字SOCKET socket(int af, int type, int protocol);
// af: 地址族 AF_INET (IPv4), AF_INET6 (IPv6)
// type: SOCK_STREAM (TCP), SOCK_DGRAM (UDP), SOCK_RAW
// protocol: 0 (自動選擇), IPPROTO_TCP, IPPROTO_UDP
// 返回: INVALID_SOCKET 失敗, 否則套接字描述符
int bind(SOCKET s, const struct sockaddr* name, int namelen);
// sockaddr_in 結構 (IPv4):
struct sockaddr_in {
short sin_family; // AF_INET
u_short sin_port; // 網絡字節序端口 (htons)
struct in_addr sin_addr; // 網絡字節序 IP (inet_addr/inet_pton)
char sin_zero[8]; // 填充
};
// 返回: 0 成功, SOCKET_ERROR 失敗
// 客戶端主動連接
int connect(SOCKET s, const struct sockaddr* name, int namelen);
// 服務器端接受連接 (阻塞直到有連接到達)
SOCKET accept(SOCKET s, struct sockaddr* addr, int* addrlen);
// 返回: 新套接字 (用於數據傳輸), INVALID_SOCKET 失敗
// addr/addrlen: 可選,返回客戶端地址信息
int listen(SOCKET s, int backlog);
// backlog: 內核未完成/已完成連接隊列最大長度 (建議 SOMAXCONN)
// 僅適用 SOCK_STREAM
int send(SOCKET s, const char* buf, int len, int flags);
int recv(SOCKET s, char* buf, int len, int flags);
// flags: MSG_DONTROUTE, MSG_OOB (帶外數據), MSG_PEEK (窺探不移除)
// 返回: 發送/接收字節數, 0 (對方關閉), SOCKET_ERROR
// 注意: TCP 為流協議,需處理「粘包/半包」應用層邊界
int select(int nfds, fd_set* readfds, fd_set* writefds, fd_set* exceptfds, const struct timeval* timeout);
// nfds: 最大套接字值 + 1 (Windows 忽略此參數)
// readfds: 關注可讀 (數據到達/連接關閉/accept 就緒)
// writefds: 關注可寫 (發送緩衝區可用/連接建立成功)
// exceptfds: 關注異常 (帶外數據等)
// timeout: NULL 永久阻塞, {0,0} 非阻塞輪詢, >0 最大等待
// 返回: 就緒套接字總數, 0 超時, SOCKET_ERROR
// 配合 FD_SET/FD_CLR/FD_ISSET/FD_ZERO 宏操作 fd_set
int closesocket(SOCKET s);
// 引用計數歸零時發送 FIN (TCP) 或直接釋放 (UDP)
// 應確保發送緩衝區數據已發完 (或設置 SO_LINGER)

關鍵點:listen 後內核為該套接字維護兩個隊列;accept 僅從「已完成連接隊列」取出,**不參與三次握手**;客戶端 connect 返回即代表握手完成。

關鍵點:無 listen/accept;bind 通常由客戶端隱式綁定臨時端口;sendto/recvfrom 攜帶目標/源地址;connect 可用於 UDP 固定對端地址 (之後可用 send/recv)。

展示服務器多進程/多線程並發模型:accept 後 fork/CreateThread 處理子連接,父進程繼續 accept。
htons()、IP htonl()/inet_pton(),接收端對應 ntohs()/ntohl()。ioctlsocket(FIONBIO)、WSAAsyncSelect、WSAEventSelect、IOCP (Completion Port) 高性能模型。recv 循環拼裝完整業務包。SO_REUSEADDR 允許端口快速重用。shutdown(s, SD_SEND) 發送 FIN → 循環 recv 讀 0 → closesocket,確保數據雙向傳輸完畢。WSAGetLastError() 獲取錯誤碼 (如 WSAEWOULDBLOCK, WSAECONNRESET)。掌握 Socket 編程,核心在於理解 **「套接字是通信端點」**、**「TCP 是可靠字節流,UDP 是不可靠數據報」**、**「內核維護連接隊列與緩衝區」**。熟練使用 select/IOCP 實現高並發,正確處理字節序、粘包、優雅關閉,即可構建穩健的網絡應用。