连接由peer重置 - winsock

时间:2014-01-01 12:11:37

标签: c++ winsock winsock2

我知道“通过对等方重置连接”意味着什么,可能这已经得到了解答,但是我找不到对不起。

我正在使用TCP创建一个客户端和服务器,并且服务器应该是24/7,当它关闭时,但是当我关闭客户端时,发送和recv由于'由peer重置连接'而失败。好吧,但问题是服务器完全挂起,只允许客户端连接,不与send / recv通信,我不假装总是重新启动服务器。

这是我正在使用的源代码:

客户端:

bool Browsify::Connect( const char* addr, unsigned short port )
{
    if(!net.isInitialized)
    {
        Log::Error( "Browsify wasn't initialized." );
        return false;
    }

    net.addr = addr;
    net.port = port;

    net.s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if(res == INVALID_SOCKET)
    {
        Log::Error( "socket() failed - %d.", WSAGetLastError() );
        return false;
    }

    sockaddr_in sk;
    memset( (char*) &sk, 0, sizeof(sk) );

    sk.sin_addr.s_addr = inet_addr( addr );
    sk.sin_port = htons( port );
    sk.sin_family = AF_INET;

    res = connect( net.s, (sockaddr*) &sk, sizeof(sk) );

    if(res == SOCKET_ERROR)
    {
        Log::Error( "connect() failed - %d.", WSAGetLastError() );
        return false;
    }

    net.isConnected = true;

    CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)
        Browsify::HandleReceive, NULL, NULL, NULL );

    return true;
}

ServerItem item[1024];

bool Browsify::HandleReceive()
{
    char buf[512];
    sprintf( buf, "getservers iw4" );
    res = send( net.s, buf, sizeof(buf), NULL );

    if(res == SOCKET_ERROR)
    {
        Log::Error( "send() failed - %d.", WSAGetLastError() );
        return false;
    }

    res = recv( net.s, (char*)&item, sizeof(item), NULL );

    if(res == SOCKET_ERROR)
    {
        Log::Error( "recv() failed - %d.", WSAGetLastError() );
        return false;
    }

    while(true)
    {
        if(res > NULL)
        {
            Browsify::QueryServer( 0 );
            // finally.. after thousands and thousands of years, I did it!
            // no winsock error, though, the server is really unstable.
            //Log::Info( "server count %d", item->serverCount );
        }
        else if(res == NULL)
        {
            Log::Warning( "Connection closed." );
        }

        Sleep( 1 );
    }

    return true;
}

服务器

bool Browsify::Listen( uint16 port )
{
    printf( "# Listening on port %u...\n", port );

    if(!net.isInitialized)
    {
        printf( "ERROR: Browsify wasn't initialized.\n" );
        return false;
    }

    net.port = port;

    net.sListen = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if(net.sListen == INVALID_SOCKET)
    {
        printf( "ERROR: socket() failed - %d.\n", WSAGetLastError() );
        return false;
    }

    sockaddr_in sk;
    memset( (char*) &sk, 0, sizeof(sk) );

    sk.sin_addr.s_addr = ADDR_ANY;
    sk.sin_port = htons( port );
    sk.sin_family = AF_INET;

    res = bind( net.sListen, (sockaddr*) &sk, sizeof(sk) );

    if(res == SOCKET_ERROR)
    {
        printf( "ERROR: bind() failed - %d.\n", WSAGetLastError() );
        return false;
    }

    res = listen( net.sListen, SOMAXCONN );

    if(res == SOCKET_ERROR)
    {
        printf( "ERROR: listen() failed - %d\n", WSAGetLastError() );
        return false;
    }

    net.sClient = accept( net.sListen, NULL, NULL );

    if(net.sClient == INVALID_SOCKET)
    {
        printf( "ERROR: accept() failed - %d\n", WSAGetLastError() );
        return false;
    }
    else
    {
        printf( "# Unknown connection accepted.\n" );
    }

    closesocket( net.sListen );
    net.isListening = true;

    CreateThread( NULL, NULL, (LPTHREAD_START_ROUTINE)
        Browsify::HandleReceive, NULL, NULL, NULL );

    return true;
}

bool Browsify::HandleReceive()
{
    char recvbuf[1024];
    res = recv( net.sClient, recvbuf, sizeof(recvbuf), NULL );

    if(res == SOCKET_ERROR)
    {
        printf( "ERROR: recv() failed - %d.\n", WSAGetLastError() );
        closesocket( net.sClient );
        WSACleanup();
        //return false;
    }

    while(true)
    {
        if(res > NULL)
        {
            if(!strcmp( recvbuf, "getservers iw4" ))
            {
                ServerItem item[1024];

                strcpy( item[0].hostname, "^1PLAY^34^1FUN ^2TDM" );
                strcpy( item[0].mapname, "mp_rust" );
                strcpy( item[0].gametype, "war" );
                strcpy( item[0].addr, "127.0.0.1" );

                item[0].currPlayers = 1;
                item[0].maxPlayers = 18;
                item[0].port = 27005;

                strcpy( item[1].hostname, "^1PLAY^34^1FUN ^2ISNIPE" );
                strcpy( item[1].mapname, "mp_terminal" );
                strcpy( item[1].gametype, "iSnipe" );
                strcpy( item[1].addr, "127.0.0.1" );

                item[1].currPlayers = 15;
                item[1].maxPlayers = 18;
                item[1].port = 27005;

                item->serverCount = 2;

                res = send( net.sClient, (char*) &item, sizeof(item), NULL );

                if(res == SOCKET_ERROR)
                {
                    printf( "send() failed - %d\n", WSAGetLastError() );
                    closesocket( net.sClient );
                    WSACleanup();
                    //return false;
                }
            }
        }
        else if(res == NULL)
        {
            printf( "Connection closed.\n" );
        }

        Sleep( 1 );
    }

    shutdown( net.sClient, SD_SEND );

    return true;
}

这就是游戏的服务器浏览器,这就是为什么它应该是24/7。

1 个答案:

答案 0 :(得分:0)

我认为问题在于您多次呼叫listen()。这不是服务器被禁止工作的方式。

进入服务器的正确方法是(伪代码):

SOCKET one_time_initialization()
{
    SOCKET listenSocket = socket(...);
    bind(listenSocket, ...);
    listen(listenSocket, ...);
    return listenSocket; //do not close the listensocket until the finishes!
}

void accept_connections(SOCKET listenSocket)
{
    for (;;) //or message driven, that depends on the application architecture
    {
        SOCKET socket = accept(listenSocket);
        //you should really create a structure/object here, add the socket in there
        //and create a thread passing the pointer to that structure as `lParam`
        Connection *data = new Connection(socket);

        CreateThread(NULL, NULL, HandleReceive, NULL, NULL, data);
        //the socket should be closed when the thread finishes and the data is deleted
    }
}