【问题标题】:Looping a socket connection attempt eventually disconnects the internet connection循环套接字连接尝试最终会断开互联网连接
【发布时间】:2012-04-24 20:29:22
【问题描述】:
char IP[30] = "127.0.0.1";
char PORT[10] = "1000";

void Connection(HWND hwnd)
{
    WORD wVersionRequested;
    WSADATA wsaData;
    char * ip = "";
    PHOSTENT hostinfo;
    wVersionRequested = MAKEWORD( 2, 0 );
    int ConRes, ConRes2;
    char Buffer [20] = "";

    if ( WSAStartup( wVersionRequested, &wsaData ) == 0 )
    {
        if((hostinfo = gethostbyname(IP)) != NULL)
        {
            ip = inet_ntoa (*(struct in_addr *)*hostinfo->h_addr_list);
        }   
    }

    InitWSA();

    begin:

    Sleep(1000);
    RemAdr.sin_family = AF_INET;
    RemAdr.sin_addr.s_addr=inet_addr(127.0.0.2);
    RemAdr.sin_port = htons (atoi(PORT));
    client = socket (AF_INET,SOCK_STREAM,0);

    switch(connect (client, (struct sockaddr *)&RemAdr,sizeof(RemAdr)))
    {
    case 0:
        WSAAsyncSelect(client,hwnd,RATMSG_SOCKET,FD_READ|FD_CLOSE|FD_CONNECT);
        return;
        break;

    default:
        Sleep(1000);    
        RemAdr.sin_family = AF_INET;
        RemAdr.sin_addr.s_addr=inet_addr(ip);
        RemAdr.sin_port = htons (atoi(PORT));
        client = socket (AF_INET,SOCK_STREAM,0);
        ConRes2=connect (client, (struct sockaddr *)&RemAdr,sizeof(RemAdr));
        break;
    }

    switch(ConRes2)
    {
    case 0:
        WSAAsyncSelect(client,hwnd,RATMSG_SOCKET,FD_READ|FD_CLOSE|FD_CONNECT);
        return;
        break;

    default:
        goto begin;
        break;
    }

    return;
}

在尝试连接几个小时但连接失败后,用户的互联网最终将断开连接,直到您关闭应用程序。似乎是什么问题?我认为我的代码有点草率,所以任何有用的提示都会很棒,很想学习。

在这个过程中,我实际上是想设法让它有一个“备用”IP 地址来连接,以防第一个失败。因此,如果无法连接到 127.0.0.1,请尝试 127.0.0.2,然后再以 127.0.0.1 为例。我该如何处理?

附:您在我的代码中看到的任何看起来像是“坏习惯”的东西,请指出,以便我将来学习/修复它。谢谢。

【问题讨论】:

    标签: c++ sockets winsock2


    【解决方案1】:

    您有句柄泄漏。如果第一个connect() 失败,您将调用socket() 分配一个新的SOCKET 句柄并将其分配给相同的client 变量,从而丢失您之前分配的SOCKET。如果对connect() 的第二次调用失败,您的循环将再次调用socket() 并将其分配给相同的client 变量,一次又一次,一次又一次,直到connect() 最终成功,如果有的话。随着时间的推移,这将浪费资源。您需要摆脱额外的socket() 调用。在进入循环之前只调用一次socket(),然后使用现有的SOCKET 为每个IP 循环调用connect()

    编辑试试这样的:

    std::string IP = "127.0.0.1";                 
    std::string IP2 = "127.0.0.2";                 
    std::string PORT = "1000";                 
    
    void Connection(HWND hwnd) 
    { 
        std::string ip[2]; 
        ip[0] = IP;
        ip[1] = IP2;
    
        memset (&RemAdr, 0, sizeof(RemAdr));
        client = INVALID_SOCKET;
    
        WORD wVersionRequested = MAKEWORD(2, 0); 
        WSADATA wsaData; 
    
        if (WSAStartup(wVersionRequested, &wsaData) == 0) 
        { 
            for (int i = 0; i < 2; ++i)
            {
                PHOSTENT hostinfo = gethostbyname(ip[i].c_str());
                if (hostinfo != NULL) 
                    ip[i] = inet_ntoa(*(struct in_addr *)(hostinfo->h_addr_list[0])); 
            }
    
            client = socket(AF_INET, SOCK_STREAM, 0); 
            if (client != INVALID_SOCKET)
            {
                RemAdr.sin_family = AF_INET;
                RemAdr.sin_port = htons(atoi(Port.c_str())); 
    
                do
                {
                    for (int i = 0; i < 2; ++i)
                    {
                        RemAdr.sin_addr.s_addr = inet_addr(ip[i].c_str()); 
    
                        if (connect(client, (struct sockaddr *)&RemAdr, sizeof(RemAdr)) == 0) 
                        { 
                            WSAAsyncSelect(client, hwnd, RATMSG_SOCKET, FD_READ | FD_CLOSE | FD_CONNECT); 
                            return; 
                        }
    
                        Sleep(1000);
                    }     
                }
                while (true); 
            }
        }
    } 
    

    【讨论】:

    • 不,它需要在循环之外。只有connect() 应该在循环内。
    • 如果 onyl connect 在循环内,我将如何更改它使用的 ip?
    • 感谢您的帮助。是您立即发现的一个简单错误。
    • 我遇到了问题。如果服务器端断开连接,这将尝试重新连接。问题是,连接上不是 == 0,我无法让它返回错误代码。服务器端第二次接受连接尝试,但由于它不 == 0 它不会去 WSAAsyncSelect 删除辅助 IP 解决了问题,但是 eh
    • connect() 如果失败则返回SOCKET_ERROR。您必须使用WSAGetLastError() 来获取实际的错误代码。
    猜你喜欢
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 1970-01-01
    • 2020-06-27
    • 1970-01-01
    • 2019-05-18
    相关资源
    最近更新 更多