1

使用 winsock 我希望我的服务器应用程序只接受来自某个(比如说192.168.0.0/24)子网的连接。

我正在考虑两种选择:

  • 每次accept连接时检查客户端的地址。

    while (true) {
        SOCKET clientSocket = accept(serverSocket, 
                                     (SOCKADDR *)&clientAddress, 
                                     &addressLenght);
        if (clientSocket == INVALID_SOCKET
        || clientAddress.sin_addr.S_un.S_un_b.s_b1 != 192 
        || clientAddress.sin_addr.S_un.S_un_b.s_b2 != 168 
        || clientAddress.sin_addr.S_un.S_un_b.s_b3 != 0) {
            closesocket(clientSocket);
            continue;
        }
    
        ...
    }
    
  • 找出相应网络的本地地址并将其用作name参数bind

    SOCKADDR_IN serverAddress;
    serverAddress.sin_family = AF_INET;
    serverAddress.sin_port = htons(13666);
    serverAddress.sin_addr.S_un.S_addr = inet_addr("192.168.0.1");
    
    result = bind(serverSocket, (SOCKADDR *)&serverAddress, 
                  sizeof(serverAddress));
    

我还有什么其他选择?

PS:有人告诉我有更好的解决方案。但我无法弄清楚。

4

2 回答 2

1

如果您只想侦听一个子网上的客户端,正确的解决方案是bind()使用单个侦听套接字连接到与该子网对应的适配器的本地 IP。让操作系统为您进行过滤。

如果您需要监听多个子网上的客户端,您可以bind()根据需要为每个子网本地 IP 设置单独的侦听套接字,也可以bind()将单个套接字连接到INADDR_ANY(0.0.0.0),然后手动过滤客户端。

如果你手动过滤,你应该使用WSAAccept()而不是accept()这样你就可以利用它的CONDITIONPROC回调。不同之处在于,在使用时accept(),客户端会被操作系统无条件地接受到队列中,并accept()在您的代码访问它们之前完全连接。改为使用时WSAAccept(),您可以更早地访问客户端远程 IP,并且可以在将单个客户端放入要连接的队列之前选择是接受还是拒绝它们。

于 2013-04-14T19:37:33.180 回答
1

如果您只想要来自服务器所在子网的连接(从您的问题中不清楚是否是这种情况),您可以使用setsockopt()将 TTL 设置为 1。该套接字的数据包(包括连接握手)应该不跨路由器。

于 2013-04-14T21:30:26.790 回答