문제

I know what 'Connection reset by peer' means, and probably this was already answered but I couldn't find it so sorry.

I'm making a client and server in TCP, and the server supposedly should be 24/7 when it's good to go but when I close the client, send and recv fails because of 'Connection reset by peer'. Alright, but the problem is that the server completely suspends and will only allow clients to connect and not to communicate with send/recv and I don't pretend to be always restarting the server.

Here's the source code I'm using:

Client:

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;
}

Server:

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;
}

This is all for a server browser of a game, that's why it should be 24/7.

도움이 되었습니까?

해결책

I think that the problem is that you are calling listen() multiple times. That's not how a server is suppossed to work.

The correct way to go in the server is (pseudo code):

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
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top