WinSock错误10061

WinSock错误10061

问题描述:

我已经使用winsock编写了一个简单的客户端/服务器应用程序。服务器和客户端通过本地主机上的TCP端口76567(只是我选择的一个随机数)连接和通信。我已经在三台台式机上测试过它,两台运行XP,另一台运行Win7,我也在四台笔记本电脑上测试过它,三台运行Win7,一台运行XP。该应用程序在所有桌面计算机和XP笔记本电脑上都能正常工作,但在客户端尝试连接到服务器时,所有三台Win7笔记本电脑都会收到错误10061!WinSock错误10061

我已关闭防火墙,但问题仍然存在,我也查看了导致此错误的原因,看起来客户端正尝试连接到非侦听服务器。但是,服务器调用listen()会成功返回!这个问题很奇怪,似乎只发生在Win7笔记本电脑上,有什么想法?

这里是我的套接字初始化代码:

// Initialise Winsock 
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
if(iResult != 0) 
{ 
    printf("WSAStartup failed: %d\n", iResult); 
} 

// Create a server socket 
ZeroMemory(&hints, sizeof(hints)); 
hints.ai_family = AF_INET; 
hints.ai_socktype = SOCK_STREAM; 
hints.ai_protocol = IPPROTO_TCP; 
hints.ai_flags = AI_PASSIVE; 

iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result); 
if(iResult != 0) 
{ 
    printf("getaddrinfo failed: %d\n", iResult); 
    WSACleanup(); 
} 

// Create a socket to listen for clients 
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol); 
if(listenSocket == INVALID_SOCKET) 
{ 
    printf("Error at socket(): %d\n", WSAGetLastError()); 

    freeaddrinfo(result); 
    WSACleanup(); 
} 

// Bind socket to ip address and port 
iResult = bind(listenSocket, result->ai_addr, (int) result->ai_addrlen); 
if(iResult == SOCKET_ERROR) 
{ 
    printf("bind failed with error: %d\n", WSAGetLastError()); 

    freeaddrinfo(result); 
    closesocket(listenSocket); 
    WSACleanup(); 
} 
freeaddrinfo(result); 

// Listen for connection requests 
if(listen(listenSocket, SOMAXCONN) != 0) 
{ 
    printf("Listen failed with error: %d\n", WSAGetLastError()); 

    closesocket(listenSocket); 
    WSACleanup(); 
} 

非常感谢:)

+1

什么防病毒应用程序在笔记本电脑上运行? – 2012-04-27 12:36:13

+0

只是标准的Windows安全的东西,虽然其中一台笔记本电脑上有Spybot。我认为这不是问题,因为桌面上安装有卡巴斯基或诺顿,我没有遇到这些机器的问题。 – StackTrace 2012-04-27 15:03:16

+0

你能显示客户代码吗?它如何确定连接哪个IP /端口? – 2012-04-28 00:24:30

getaddrinfo()返回给定hints条件的所有可用地址的链接列表。即使机器只有一个网络适配器,它也可能有多个分配给它的IP地址,即使是本地主机也是如此。您将服务器套接字绑定到getaddrinfo()找到的第一个IP /端口对,因此客户端可能试图连接到实际上未在服务器上侦听的其他IP /端口,例如服务器绑定到您的LAN/Internet IP,但客户端连接到127.0.0.1。除非服务器绑定到127.0.0.1,否则客户端无法连接到127.0.0.1

在多宿主/多IP环境中,你应该在调用bind()的时候,而不是result->ai_addr使用通配符0.0.0.0 IP(又名INADDR_ANY)。这将将套接字绑定到所有已安装网络适配器的所有可用IP。这样,客户端就可以连接到服务器绑定的任何IP,包括127.0.0.1。事实上,由于你已经显示的代码,你甚至都不需要使用getaddrinfo()都:

// Initialise Winsock 
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData); 
if(iResult != 0) 
{ 
    printf("WSAStartup failed: %d\n", iResult); 
} 

// Create an IPv4 server socket to listen for IPv4 clients 
listenSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); 
if(listenSocket == INVALID_SOCKET) 
{ 
    printf("Error at socket(): %d\n", WSAGetLastError()); 
    WSACleanup(); 
} 

// Bind socket to IPv4 address and port 
sockaddr_in addr; 
memset(&addr, 0, sizeof(addr)); 
addr.sin_family = AF_INET; 
addr.sin_port = htons(76567); 
addr.sin_addr.s_addr = INADDR_ANY; 

iResult = bind(listenSocket, (sockaddr*)&addr, sizeof(addr)); 
if(iResult == SOCKET_ERROR) 
{ 
    printf("bind failed with error: %d\n", WSAGetLastError()); 
    closesocket(listenSocket); 
    WSACleanup(); 
} 

// Listen for IPv4 connection requests 
if(listen(listenSocket, SOMAXCONN) != 0) 
{ 
    printf("Listen failed with error: %d\n", WSAGetLastError()); 
    closesocket(listenSocket); 
    WSACleanup(); 
} 
+0

好主意,我试过了,但我得到同样的问题。在桌面上运行良好,但不能在win7笔记本电脑上运行。感谢Remy的建议:) – StackTrace 2012-05-01 10:53:32

+0

然后使用命令行'netstat'工具或SysInternal的TCPView工具来验证服务器是否实际正在侦听客户端试图连接的IP /端口,然后确保客户端实际上是试图连接到你认为应该连接的IP /端口。 – 2012-05-01 22:35:42

+0

对套装软件快看,它显示了这一点: 协议:TCP 本地地址: 本地端口:11031个 远程地址: 远程端口:0 状态:聆听 让我困惑的是我将端口设置为76567.但本地端口或远程端口均未设置为此。再次感谢雷米。 – StackTrace 2012-05-08 10:27:33

IP端口是16位整数,因此允许的最大端口号为0xFFFF(65535)。这里发生的是一种整数溢出。由于您希望的端口号(76567)不适合16位,因此该数字将被截断,只使用最低16位。这给你端口号11031.行addr.sin_port = htons(76567);应该给你一个编译器警告,因为参数htons()不能finode uint16_t