在接受连接 C++ 之前获取套接字的 IP 地址

Posted

技术标签:

【中文标题】在接受连接 C++ 之前获取套接字的 IP 地址【英文标题】:Get socket's IP address before accepting connection C++ 【发布时间】:2012-04-22 00:33:57 【问题描述】:

我需要获取连接的 IP 地址以查看它之前是否已连接(检查 ips 列表,如果它之前已连接但不再连接,它将显示离线)。 (使用非阻塞套接字)

如何在不接受IP的情况下获得IP。

///

    case FD_ACCEPT:
        int W;
        for(W = 0;W <= ListView_GetItemCount(GetDlgItem(HwND,IDC_IPLIST));W++)

那么我将根据列表视图检查 IP 以查看它之前是否已连接。如果有,我想使用上次使用的相同套接字号。

这就是我现在接受连接的方式

        case FD_ACCEPT: 
        while(Client[F] != NULL)
        
        F++;
        
        Client[F]=accept(wParam,(LPSOCKADDR)&ServAdr,&AdrLen);
        break;

所以把它分解...

我想根据以前连接的 IP 列表检查传入连接。此列表将包含 IP 及其是否在线/离线(已连接/未连接)。如果它在我希望它在我接受新连接时显示在线之前已经连接,并使用它上次使用的相同套接字号,而不是一起使用一个新的。如果没有,我希望将其添加到列表中。 (列表将有套接字号)

如果这没有多大意义,我会尝试澄清更多。

【问题讨论】:

Refusing connection from a host 的可能重复项 当然,这会破坏带有 NAT 的用户。 【参考方案1】:

accept() 无法满足您的要求。在连接被接受并分配新的SOCKET 句柄之前,您无法访问连接的信息。要获得连接信息预接受,您必须改用WSAAccept()的回调功能。

无论哪种方式,都无法为新连接重用现有的SOCKET 句柄。每个接受的连接都必须有自己唯一的SOCKET 句柄。不过,您当然可以将来自先前看到的 IP 的新连接与 ListView 中的现有插槽相关联。

【讨论】:

【参考方案2】:

如果 socket number 是指accept() 返回的数字,则根本不能依赖它的值。我的意思是,如果远程主机断开连接并再次连接,accept() 返回的值很可能会有所不同。依赖这个数字是没有意义的。

如果 socket number 是指数组中的位置,则可以将 accept() 返回的值分配给临时变量:

SOCKET tmpSock;
sockaddr_in tmpAddr;
int namelen;
typedef struct  /*...*/  TClient;
TClient Client[MAX_CLIENTS];
/*...*/
tmpSock = accept(/*...*/);
namelen = sizeof(tmpAddr);
getpeername(tmpSock, (sockaddr*)&tmpAddr,&namelen);
/*...*/
//looking for tmpAddr.sin_addr in your list and calculating
//the list position - F
/*...*/
Client[F].Socket = tmpSock;
Client[F].IsConnected = true;
Client[F].Address = tmpAddr.sin_addr;

请记住,在listen() 调用之后,操作系统内核将接受所有传入连接到您设置的端口/本地 IP。这意味着无论您是否调用accept(),远程主机的connect()都会成功返回(前提是您在侦听队列中有空间)。调用accept() 将只允许您与套接字进行交互。它不会改变远程主机看到的连接状态。

【讨论】:

感谢大家的帮助,Pavel 的建议很好!【参考方案3】:

我不确定实现您想要的是否可能也不是有效的规范。我会:

    接受任何连接,然后检查 IP 地址,断开不在列表中的连接

    (这可能不适合你)配置上游防火墙,只允许允许的 IP 地址通过。

【讨论】:

很好的答案,谢谢。在某些情况下,同时执行 #1 和 #2 可能是有益/必要的。例如,如果您需要向不同的客户端发送不同的数据。【参考方案4】:

如果您绑定到通配符地址 (INADDR_ANY),则在连接进入之前不会确定用于通信的 IP 地址(它将来自数据包通过的接口)。同一个侦听套接字可能会导致接受多个 IP 地址上的连接。

如果您绑定到特定地址,那么您已经知道您绑定到的地址。

【讨论】:

以上是关于在接受连接 C++ 之前获取套接字的 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 IOCP 获取客户端真实 IP 地址和端口?

在Python中,当在localhost上接受TCP套接字连接时,无法获得正确的对等体IP地址。

Boost asio socket:如何获取IP,连接的端口地址?

线程中的套接字接受所有端口连接? C++

如何让套接字仅接受来自本地主机的连接(在 Java 中)?

仅启用来自指定 IP 地址的传入连接