Winsock 错误 10093 是 WSANOTINITIALISED:
尚未执行成功的 WSAStartup。
应用程序没有调用 WSAStartup 或 WSAStartup 失败。应用程序可能正在访问当前活动任务不拥有的套接字(即尝试在任务之间共享套接字),或 WSACleanup 已被调用太多次。
当accept() 因任何原因失败时,您的Network::Accept() 方法正在调用WSACleanup()。 Network::Accept() 根本不应该这样做。它也不应该关闭监听套接字。从Network::Accept() 中删除这两行,然后让你的主循环停止调用Network::Accept(),如果它返回false,然后根据需要清理你的监听套接字。
您的Network::Accept() 代码还有其他问题:
accept() 返回 SOCKET,而不是 int。
当accept() 成功时,您正在调用带有错误参数值的getpeername()。您传递的是侦听套接字而不是接受的客户端套接字,并且您为其 namelen 参数传递了一个无效指针(您需要传递一个指向您的 caddrlen 值的指针,而不是类型转换的返回值sizeof())。就此而言,调用getpeername() 无论如何都是多余的,因为accept() 已经为您提供了与getpeername() 相同的地址。
在调用inet_ntop() 时,您将客户端地址的sin_addr 字段类型转换为sockaddr*,这是错误的。但在这种情况下,编译器接受它,因为pAddr 参数是void*。你根本不需要类型转换。
1234563 )。但是,如果您想要/需要支持 IPv6(并且您应该),那么您应该检查客户端的实际地址系列,以了解该地址是使用 sockaddr_in 还是 sockaddr_in6,然后相应地将参数传递给 inet_ntop() .
话虽如此,请尝试更多类似的东西:
如果您仅支持 IPv4:
bool Network::Accept() {
// declare clientAddr as sockaddr_in...
caddrlen = sizeof(clientAddr);
SOCKET ret = accept(listeningSocket, (struct sockaddr*)&clientAddr, &caddrlen);
if (ret == INVALID_SOCKET) {
myFormatMessage(WSAGetLastError());
return false;
}
//save client ip address in a string
char ip[INET_ADDRSTRLEN] = {0};
inet_ntop(AF_INET, &(clientAddr.sin_addr), ip, INET_ADDRSTRLEN);
clientIPaddr.assign(ip);
// declare connectedSocket as SOCKET...
connectedSocket = ret;
return true;
}
如果您仅支持 IPv6:
bool Network::Accept() {
// declare clientAddr as sockaddr_in6...
caddrlen = sizeof(clientAddr);
SOCKET ret = accept(listeningSocket, (struct sockaddr*)&clientAddr, &caddrlen);
if (ret == INVALID_SOCKET) {
myFormatMessage(WSAGetLastError());
return false;
}
//save client ip address in a string
char ip[INET6_ADDRSTRLEN] = {0};
inet_ntop(AF_INET6, &(clientAddr.sin6_addr), ip, INET6_ADDRSTRLEN);
clientIPaddr.assign(ip);
// declare connectedSocket as SOCKET...
connectedSocket = ret;
return true;
}
如果您同时支持 IPv4 和 IPv6:
bool Network::Accept() {
// declare clientAddr as SOCKADDR_STORAGE...
caddrlen = sizeof(clientAddr);
SOCKET ret = accept(listeningSocket, (struct sockaddr*)&clientAddr, &caddrlen);
if (ret == INVALID_SOCKET) {
myFormatMessage(WSAGetLastError());
return false;
}
//save client ip address in a string
char ip[INET6_ADDRSTRLEN] = {0};
switch (clientAddr.ss_family)
{
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in*)&clientAddr)->sin_addr), ip, INET_ADDRSTRLEN);
break;
case AF_INET6:
inet_ntop(AF_INET6, &((struct sockaddr_in6*)&clientAddr)->sin6_addr), ip, INET6_ADDRSTRLEN);
break;
}
clientIPaddr.assign(ip);
// declare connectedSocket as SOCKET...
connectedSocket = ret;
return true;
}