2

我需要获取连接的 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 及其是否在线/离线(已连接/未连接)。如果它在我希望它在我接受新连接时显示在线之前已经连接,并使用它上次使用的相同套接字号,而不是一起使用一个新的。如果没有,我希望将其添加到列表中。(列表将有套接字号)

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

4

4 回答 4

2

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

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

于 2012-04-22T04:07:33.663 回答
1

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

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

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

于 2012-04-22T01:37:49.167 回答
1

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

如果通过套接字编号表示数组中的位置,则可以将返回的值分配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 的所有传入连接。这意味着connect()无论您是否调用远程主机都会成功返回accept()(前提是您在侦听队列中有空间)。调用accept()将只允许您与套接字交互。它不会改变远程主机看到的连接状态。

于 2012-04-22T03:54:23.717 回答
0

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

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

于 2012-04-22T05:25:20.117 回答