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开始不是一个,所以当我定义MAX_CLIENTS为2时,我在Max中递减它,以便唯一可用的将是0和1.我将查看std :: map并改进代码,而且我没有考虑过使用同一个IP的客户端,所以我一定会添加它。但我很好奇1如何无效? – NukingDragons 2014-09-18 22:39:47
如果您创建大小为1的数组,则其中唯一的索引为0,因为索引从零开始。如果你有一个大小为1的数组,那么唯一有效的索引是[0]。如果你有一个大小为2的数组,那么有效索引是在[0]和[1]。 – 2014-09-18 22:44:42
好的。我认为如果我把1放进去,它会允许0和1,如果我把0放进去,它只会是0.所以我认为我输入的数字是它可以达到的最大值。感谢您指点我正确的方向 – NukingDragons 2014-09-18 22:48:02