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

问题描述:

我想让我的服务器分配客户端ID,但是每当我将客户端连接到服务器时,服务器崩溃。Winsock2错误:连接到客户端时服务器崩溃

服务器:

#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是哪个,然后当我需要发送的数据包对于客户,我可以通过Address[ ID ];参考客户ID来完成。服务器和客户端运行正常,没有客户端ID的代码。请帮忙。任何关于如何改进代码或其他方式来做到这一点的建议都没有问题。

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

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

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

+0

我认为数组从0开始不是一个,所以当我定义MAX_CLIENTS为2时,我在Max中递减它,以便唯一可用的将是0和1.我将查看std :: map并改进代码,而且我没有考虑过使用同一个IP的客户端,所以我一定会添加它。但我很好奇1如何无效? – NukingDragons 2014-09-18 22:39:47

+0

如果您创建大小为1的数组,则其中唯一的索引为0,因为索引从零开始。如果你有一个大小为1的数组,那么唯一有效的索引是[0]。如果你有一个大小为2的数组,那么有效索引是在[0]和[1]。 – 2014-09-18 22:44:42

+0

好的。我认为如果我把1放进去,它会允许0和1,如果我把0放进去,它只会是0.所以我认为我输入的数字是它可以达到的最大值。感谢您指点我正确的方向 – NukingDragons 2014-09-18 22:48:02