我正在使用MinGW编译器和winsock2 API为Windows编写自定义TCP服务器。
我有这段代码:
TCPSocket TCPSocket::accept() {
TCPSocket clSocket;
struct sockaddr_in clAddr;
socklen_t clAddrSize;
clAddrSize = sizeof(clAddr);
clSocket.shared->sockFd = ::accept(shared->sockFd, (struct sockaddr *)&clAddr, &clAddrSize);
if (clSocket.shared->sockFd < 0) {
printf("failed to accept incoming connection (code: %d)\n", WSAGetLastError());
throw SocketException(6, "failed to accept incoming connection");
}
clSocket.shared->buffer = new byte [BUFFER_SIZE];
clSocket.shared->curPos = clSocket.shared->endPos = clSocket.shared->buffer;
return clSocket;
}
但是在调用accept()之后我得到了
failed to accept incoming connection (code: 10014)
根据MSDN:
WSAEFAULT 10014 地址不好。 在尝试使用调用的指针参数时,系统检测到无效的指针地址。如果应用程序发生此错误 传递无效的指针值,或者缓冲区的长度也是如此 小。例如,如果一个参数的长度,这是一个sockaddr 结构,小于sizeof(sockaddr)。
我没有看到,这些指针如何变坏,它们都直接解决了局部变量。 clAddrSize
已初始化,shared->sockFd
在另一个函数中初始化
void TCPSocket::listen(uint16_t port, int backlog) {
struct addrinfo * ainfo;
char portStr[8];
int res;
if (shared->sockFd != -1)
logicError(1, "socket already initialized, need to close first");
snprintf(portStr, sizeof(portStr), "%hu", (ushort)port);
if (getaddrinfo("localhost", portStr, NULL, &ainfo) != 0)
systemError(2, "failed to retrieve info about localhost", false);
shared->sockFd = socket(ainfo->ai_family, SOCK_STREAM, IPPROTO_TCP);
if (shared->sockFd < 0)
systemError(3, "failed to create a TCP socket", false);
res = bind(shared->sockFd, ainfo->ai_addr, ainfo->ai_addrlen);
if (res != 0)
systemError(5, "failed to bind socket to local port", true);
res = ::listen(shared->sockFd, backlog);
if (res != 0)
systemError(6, "failed to set socket to listen state", true);
freeaddrinfo(ainfo);
}
你看到我忽略了什么吗?
答案 0 :(得分:1)
好的,感谢CristiFati我发现了问题。 使用这种方式的函数getaddrinfo(&#34; localhost&#34;,portStr,NULL和&amp; ainfo)返回一个IPv6地址。虽然接受了sockaddr_in,这是IPv4地址的结构。
可能有更多方法可以解决,例如
但我选择以这种方式手动为IPv4协议初始化套接字:
struct sockaddr_in myAddr;
memset(&myAddr, 0, sizeof(myAddr));
myAddr.sin_family = AF_INET;
myAddr.sin_port = htons((ushort)port);
shared->sockFd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (shared->sockFd < 0)
systemError(3, "failed to create a TCP socket", false);
res = bind(shared->sockFd, (struct sockaddr *)&myAddr, sizeof(myAddr));
if (res != 0)
systemError(5, "failed to bind socket to local port", true);
从那以后,一切正常。