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

Windows 下 C++ Socket 服務器開發(三):Winsock 初始化、Socket 創建與綁定監聽詳解

     編輯:C++ 入門

Winsock 初始化:WSAStartup 詳解

Windows 平台調用 Socket API 前,必須調用 WSAStartup 載入 Winsock DLL 並協商版本:

WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
    // 錯誤處理
    return -1;
}
// 檢查實際版本
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
    WSACleanup();
    return -1;
}
  • MAKEWORD(2,2) 請求 2.2 版本(主版本 2,副版本 2),比舊教程常見的 1.1 更現代。
  • LOBYTE/HIBYTE 宏從 wVersion 提取主/副版本號。
  • 失敗時必須調用 WSACleanup() 釋放資源。

Socket 創建:socket()

SOCKET tcp_socket = socket(AF_INET, SOCK_STREAM, 0);
參數值含義
afAF_INETIPv4 協議族
typeSOCK_STREAM面向連接、可靠的字節流(TCP)
protocol0自動選擇協議(TCP 對應 IPPROTO_TCP)

返回 INVALID_SOCKET 表示失敗,需檢查 WSAGetLastError()。

地址結構 sockaddr_in 配置

sockaddr_in saddr{};
saddr.sin_family = AF_INET;
saddr.sin_port = htons(port);          // 主機序轉網絡序
saddr.sin_addr.s_addr = INADDR_ANY;    // 綁定所有本地接口
  • sin_zero[8] 僅為填充對齊,無實際業務含義。
  • INADDR_ANY 允許服務器接受任意網卡上的連接請求。

綁定與監聽:bind() & listen()

bind() 綁定地址

if (::bind(tcp_socket, (sockaddr*)&saddr, sizeof(saddr)) == SOCKET_ERROR) {
    // 錯誤處理:地址已被佔用、權限不足等
}

關鍵點:使用 ::bind 顯式指定全局命名空間,避免與 std::bind 冲突(若有 using namespace std;)。

listen() 進入監聽狀態

if (::listen(tcp_socket, SOMAXCONN) == SOCKET_ERROR) {
    // 錯誤處理
}
  • backlog 參數指定內核等待隊列最大長度,SOMAXCONN 為系統默認最大值。
  • 隊列滿時新連接在 TCP 層會被重試,非立即拒絕。

完整初始化流程封裝

int make_server_socket(int port) {
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2,2), &wsaData) != 0) return -1;
    if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
        WSACleanup(); return -1;
    }
    SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
    if (s == INVALID_SOCKET) { WSACleanup(); return -1; }
    sockaddr_in addr{};
    addr.sin_family = AF_INET;
    addr.sin_port = htons(port);
    addr.sin_addr.s_addr = INADDR_ANY;
    if (::bind(s, (sockaddr*)&addr, sizeof(addr)) == SOCKET_ERROR) {
        closesocket(s); WSACleanup(); return -1;
    }
    if (::listen(s, SOMAXCONN) == SOCKET_ERROR) {
        closesocket(s); WSACleanup(); return -1;
    }
    return (int)s; // 32位下安全,64位建議返回 SOCKET 類型
}

總結

掌握 WSAStartup 版本協商、socket/bind/listen 三部曲、網絡字節序轉換(htons)、全局 ::bind 避免命名冲突,是構建健壯 Windows Socket 服務器的基石。下一篇將講解 accept 循環與客戶端通訊處理。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved