仅接受来自特定子网的连接

时间:2013-04-14 16:48:08

标签: c++ winsock

使用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;
        }
    
        ...
    }
    
  • 找出相应网络的本地地址,并将其用作bind

    中的name参数
    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));
    

我还有其他选择吗?

P.S。:有人告诉我,有一个更好的解决方案。但我无法理解。

2 个答案:

答案 0 :(得分:1)

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

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

如果您手动过滤,则应使用WSAAccept()代替CONDITIONPROC,以便可以使用其accept()回调。不同之处在于,当使用accept()时,操作系统无条件地将客户端接入队列,并在代码访问它们之前由WSAAccept()完全连接。当使用{{1}}代替时,您可以更早地访问客户端远程IP,并可以选择在将各个客户端放入要连接的队列之前接受还是拒绝它们。

答案 1 :(得分:1)

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