为服务器创建套接字

初始化后,必须实例化 SOCKET 对象以供服务器使用。

为服务器创建套接字

  1. getaddrinfo 函数用于确定 sockaddr 结构中的值:

    • AF_INET 用于指定 IPv4 地址系列。
    • SOCK_STREAM 用于指定流套接字。
    • IPPROTO_TCP 用于指定 TCP 协议 。
    • AI_PASSIVE 标志指示调用方打算在 调用绑定 函数时使用返回的套接字地址结构。 如果设置了 AI_PASSIVE 标志,并且 getaddrinfo 函数的 nodename 参数为 NULL 指针,则套接字地址结构的 IP 地址部分将设置为 IPv4 地址的 INADDR_ANY,或 iPv6 地址的 IN6ADDR_ANY_INIT
    • 27015 是与客户端将连接到的服务器关联的端口号。

    addrinfo 结构由 getaddrinfo 函数使用。

    #define DEFAULT_PORT "27015"
    
    struct addrinfo *result = NULL, *ptr = NULL, hints;
    
    ZeroMemory(&hints, sizeof (hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;
    
    // Resolve the local address and port to be used by the server
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if (iResult != 0) {
        printf("getaddrinfo failed: %d\n", iResult);
        WSACleanup();
        return 1;
    }
    
  2. 为服务器创建名为 ListenSocket 的 SOCKET 对象,以侦听客户端连接。

    SOCKET ListenSocket = INVALID_SOCKET;
    
  3. 调用 套接字 函数并将其值返回到 ListenSocket 变量。 对于此服务器应用程序,请使用调用 getaddrinfo 返回的第一个 IP 地址,该地址与 hints 参数中指定的地址系列、套接字类型和协议匹配。 在此示例中,请求了 IPv4 的 TCP 流套接字,地址系列为 IPv4,套接字类型为 SOCK_STREAM,协议为 IPPROTO_TCP。 因此,为 ListenSocket 请求 IPv4 地址。

    如果服务器应用程序想要侦听 IPv6,则需要在 hints 参数中将地址系列设置为 AF_INET6。 如果服务器想要同时侦听 IPv6 和 IPv4,则必须创建两个侦听套接字,一个用于 IPv6,另一个用于 IPv4。 应用程序必须单独处理这两个套接字。

    Windows Vista 和更高版本提供创建单个 IPv6 套接字的功能,该套接字置于双堆栈模式以侦听 IPv6 和 IPv4。 有关此功能的详细信息,请参阅 双堆栈套接字

    // Create a SOCKET for the server to listen for client connections
    
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    
  4. 检查错误以确保套接字是有效的套接字。

    if (ListenSocket == INVALID_SOCKET) {
        printf("Error at socket(): %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }
    

下一步: 绑定套接字

使用 Winsock 入门

初始化 Winsock

Winsock 服务器应用程序