Winsock2错误:连接到客户端时服务器崩溃

时间:2014-09-18 22:27:03

标签: c++ winsock2

我正在尝试让我的服务器分配客户端ID,但每当我将客户端连接到服务器时,服务器都会崩溃。

服务器:

#include <iostream>
#include <winsock2.h>
#include <string>

#define PORT 25444
#define MAX_CLIENTS 2
#define BUFLEN 512

int main()
{

    SOCKET s;

    unsigned int Max = MAX_CLIENTS - 1;
    unsigned int ID[ Max ];

    std::string Address[ Max ];

    struct sockaddr_in server, si_other;

    int slen, recv_len;

    char buf[ BUFLEN ];

    WSADATA wsa;

    slen = sizeof( si_other );

    if ( WSAStartup( MAKEWORD( 2, 2 ), & wsa ) != 0 )
    {

        std::cout << "NETWORK ERROR: Failed to initialise. Error code: " << WSAGetLastError() << "\n";

    }

    if ( ( s = socket( AF_INET, SOCK_DGRAM, 0 ) ) == INVALID_SOCKET )
    {

        std::cout << "NETWORK ERROR: Failed to create socket. Error code: " << WSAGetLastError() << "\n";

    }

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = INADDR_ANY;
    server.sin_port = htons( PORT );

    if ( bind( s, ( struct sockaddr * ) & server, sizeof( server ) ) == SOCKET_ERROR )
    {

        std::cout << "NETWORK ERROR: Failed to bind to port. Error Code: " << WSAGetLastError() << "\n";

    }

    while( 1 )
    {

        bool AddClient;
        unsigned int TimesLooped;

        memset( buf, '\0', BUFLEN );

        if ( ( recv_len = recvfrom( s, buf, BUFLEN, 0, ( struct sockaddr * ) & si_other, & slen ) ) == SOCKET_ERROR )
        {

            std::cout << "NETWORK ERROR: Failed to read from the port. Error code: " << WSAGetLastError() << "\n";

        }
        else
        {

            TimesLooped = 0;

            for ( int i = 0; i <= Max; i++ )
            {

                if ( inet_ntoa( si_other.sin_addr ) != Address[ i ] )
                {

                    AddClient = true;

                }
                else
                {

                    AddClient = false;

                    i = Max;

                }

                TimesLooped++;

            }

            if ( AddClient )
            {

                Address[ TimesLooped ] = inet_ntoa( si_other.sin_addr );
                ID[ TimesLooped ] = TimesLooped;

            }

        }

        std::cout << "NETWORK: Received packet from " << inet_ntoa( si_other.sin_addr ) << ":" << ntohs( si_other.sin_port ) << "( Client ID: " << ID[ TimesLooped ] << " )" << "\n";
        std::cout << "NETWORK: Data: " << buf << "\n";

        if ( sendto( s, buf, recv_len, 0, ( struct sockaddr * ) & si_other, slen ) == SOCKET_ERROR )
        {

            std::cout << "NETWORK ERROR: Failed to send data through the port. Error code: " << WSAGetLastError() << "\n";

        }

    }

    closesocket( s );

    WSACleanup();

    return 0;

}

客户端:

#include <string>
#include <iostream>
#include <winsock2.h>

#define IP "127.0.0.1"
#define PORT 25444
#define BUFLEN 512

using namespace std;

void SendPacket( string message )
{

    struct sockaddr_in si_other;

    int s, slen = sizeof( si_other );

    char buf[ BUFLEN ];

    char msg[ BUFLEN ];

    strcpy( msg, message.c_str() );

    WSADATA wsa;

    if ( WSAStartup( MAKEWORD( 2, 2 ), & wsa ) != 0 )
    {

        cout << "ERROR: Network failed to initialise. Error code: " << WSAGetLastError() << "\n";

    }

    if ( ( s = socket( AF_INET, SOCK_DGRAM, IPPROTO_UDP ) ) == INVALID_SOCKET )
    {

        cout << "ERROR: Network failed to create socket. Error code: " << WSAGetLastError() << "\n";

    }

    memset( ( char * ) & si_other, 0, sizeof( si_other ) );
    si_other.sin_family = AF_INET;
    si_other.sin_port = htons( PORT );
    si_other.sin_addr.S_un.S_addr = inet_addr( IP );

    if ( sendto( s, msg, strlen( msg ), 0, ( struct sockaddr * ) & si_other, slen ) == SOCKET_ERROR )
    {

        cout << "ERROR: Network failed to send data through the port. Error code: " << WSAGetLastError() << "\n";

    }

    memset( buf, '\0', BUFLEN );

    if ( recvfrom( s, buf, BUFLEN, 0, ( struct sockaddr * ) & si_other, & slen ) == SOCKET_ERROR )
    {

        cout << "ERROR: Network failed to read from the port. Error code: " << WSAGetLastError() << "\n";

    }

    closesocket( s );

    WSACleanup();

}

int main()
{

    SendPacket( "Test" );

    return 0;

}

我希望能够拥有客户端ID,以便我可以跟踪哪个IP是哪个,然后当我需要向客户端发送数据包时,我可以通过{{1引用客户端ID来实现}}。服务器和客户端运行良好,没有客户端ID的代码。请帮忙。有关如何改进代码或其他方法的任何建议都很好。

1 个答案:

答案 0 :(得分:0)

在您的代码中,您的Address数组只有一个元素。 MAX_CLIENTS为2. Max为2 - 1或1,因此只有Address [0]有效。你从0循环到1,所以每次你引用索引1时,我都不会惊讶地看到崩溃。

看看std :: map,例如here.字典将处理搜索。我会使用std :: map来处理客户端ID表。

此外,您的客户端密钥仅使用IP地址,而不是客户端端口。如果两个客户端从同一IP地址连接,则它们将共享您的客户端ID。您可能希望在ID字符串中包含端口号。