在Visual C ++中接受来自客户端(套接字编程)的连接的问题

我在Visual C ++中编写了一个简单的单线程客户端服务器应用程序。 当我运行我的服务器时,我等待一段时间它接受来自客户端的一些请求。

当我将客户端连接到服务器时。 客户端上的日志消息报告发送14个字节,服务器上没有消息。 我已经编写了一个print语句来打印控制台上服务器接受的任何内容,但服务器不打印任何内容。

在我看来,客户端已连接到其他服务器。

客户端和服务器代码如下。

服务器代码

#ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include  #include  #include  #include  #include  #include  #define DEFAULT_PORT "27015" #define DEFAULT_BUFLEN 512 #pragma comment(lib, "Ws2_32.lib") int main() { WSADATA wsdata; int result = WSAStartup(MAKEWORD(2,2),&wsdata); if (result != 0){ printf("%s","Unable to initilize windows socket\n"); getch(); return 1; } struct addrinfo *addrResult = NULL,hints; ZeroMemory(&hints, sizeof (hints)); hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_protocol = IPPROTO_TCP; hints.ai_flags = AI_PASSIVE; result = getaddrinfo(NULL,DEFAULT_PORT,&hints,&addrResult); if (result != 0){ printf("%s","Error in getaddrInfo"); getch(); return 1; } SOCKET listenSocket = INVALID_SOCKET; listenSocket = socket(addrResult->ai_family,addrResult->ai_socktype,addrResult->ai_protocol); if (listenSocket == INVALID_SOCKET){ printf("%s","Error in creating socket object\n"); getch(); closesocket(listenSocket); WSACleanup(); return 1; } sockaddr_in service; service.sin_family = AF_INET; service.sin_addr.s_addr = inet_addr("127.0.0.1"); service.sin_port = htons(27015); if (bind(listenSocket,addrResult->ai_addr, (int)addrResult->ai_addrlen) == SOCKET_ERROR){ //if(bind(listenSocket,(SOCKADDR*) &service, // sizeof(service)) == SOCKET_ERROR){ printf("bind failed: %d\n", WSAGetLastError()); freeaddrinfo(addrResult); closesocket(listenSocket); WSACleanup(); getch(); return 1; } freeaddrinfo(addrResult); if (listen(listenSocket,SOMAXCONN) == SOCKET_ERROR){ printf("%s","Error in listening socket"); getch(); closesocket(listenSocket); WSACleanup(); } SOCKET clientSocket = INVALID_SOCKET; clientSocket = accept((listenSocket,NULL,NULL); if (clientSocket == INVALID_SOCKET){ closesocket(listenSocket); WSACleanup(); } char recvbuf[DEFAULT_BUFLEN]; int iRecvResult, iSendResult; int recvbuflen = DEFAULT_BUFLEN; do{ iRecvResult = 0; iSendResult = 0; iRecvResult = recv(clientSocket,recvbuf,recvbuflen,0); if (iRecvResult > 0){ printf("Bytes received: %d\n", iRecvResult); getch(); // Echo the buffer back to the sender iSendResult = send(clientSocket, recvbuf, iRecvResult, 0); if (iSendResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } printf("Bytes sent: %d\n", iSendResult); } else if (iRecvResult == 0){ printf("Connection closing...\n"); } else{ printf("recv failed: %d\n", WSAGetLastError()); closesocket(clientSocket); WSACleanup(); return 1; } }while(iRecvResult > 0); getch(); return 0; } 

客户代码

 #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN #endif #include  #include  #include  #include  #include  #include  #define DEFAULT_PORT "27015" #define DEFAULT_BUFLEN 512 #pragma comment(lib, "Ws2_32.lib") int main(){ WSADATA wsdata; WSAStartup(MAKEWORD(2,2),&wsdata); struct addrinfo *addrResult = NULL,hints; ZeroMemory(&hints, sizeof (hints)); hints.ai_protocol = IPPROTO_TCP; hints.ai_socktype = SOCK_STREAM; hints.ai_family = AF_UNSPEC; int result = 0; if (getaddrinfo("127.0.0.1",DEFAULT_PORT, &hints,&addrResult)){ printf("%s","Error in getaddrInfo\n"); WSACleanup(); getch(); return 1; } SOCKET connectingSocket = INVALID_SOCKET; connectingSocket = socket(addrResult->ai_family,addrResult->ai_socktype, addrResult->ai_protocol); if (connectingSocket == INVALID_SOCKET){ printf("%s","Error in creating socket\n"); freeaddrinfo(addrResult); WSACleanup(); getch(); return 1; } if (connect(connectingSocket,addrResult->ai_addr, (int)addrResult->ai_addrlen) != 0){ closesocket(connectingSocket); connectingSocket = INVALID_SOCKET; WSACleanup(); } freeaddrinfo(addrResult); int recvbuflen = DEFAULT_BUFLEN; char *sendbuf = "this is a test"; char recvbuf[DEFAULT_BUFLEN]; int iResult; // Send an initial buffer iResult = send(connectingSocket, sendbuf, (int) strlen(sendbuf), 0); if (iResult == SOCKET_ERROR) { printf("send failed: %d\n", WSAGetLastError()); closesocket(connectingSocket); WSACleanup(); return 1; } printf("Bytes Sent: %ld\n", iResult); // shutdown the connection for sending since no more data will be sent // the client can still use the connectingSocket for receiving data iResult = shutdown(connectingSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %d\n", WSAGetLastError()); closesocket(connectingSocket); WSACleanup(); return 1; } // Receive data until the server closes the connection do { iResult = recv(connectingSocket, recvbuf, recvbuflen, 0); if (iResult > 0) printf("Bytes received: %d\n", iResult); else if (iResult == 0) printf("Connection closed\n"); else printf("recv failed: %d\n", WSAGetLastError()); } while (iResult > 0); getch(); return 0; } 

嗯…在修复了明显的语法错误( clientSocket = accept((listenSocket,NULL,NULL);的未匹配的开括号clientSocket = accept((listenSocket,NULL,NULL); )之后,它对我来说似乎运行得相当好。在服务器上我得到:

收到的字节数:14
发送的字节数:14
连接关闭……

在客户端:

发送的字节数:14
收到的字节数:14
recv失败:10054

因此,客户端向服务器发送14个字节(按Enter键),服务器将这14个字节回送给客户端(再次按Enter键),服务器关闭连接。 客户端读取14个字节,然后在连接关闭时进一步读取失败。

编辑:我通过打开两个Windows SDK命令提示符窗口运行代码,在一个中运行server在另一个中运行client – 没有任何特别令人兴奋或不寻常的任何一个。

当客户端通过增强诊断尝试发送时,您可以确认服务器代码中发生的情况。 在重要时间输出更多(例如成功的connect()accept()close() ,所有套接字错误,可选的send/recv流量日志文件)可能会很快指向解决方案。 确保检查并输出所有套接字API调用的任何错误。

您可以使用netstat检查侦听目标端口/地址的其他系统。

我看不出任何明显的错误。

我建议你做以下事情:

  • 为了实验,从代码中删除所有getch()
  • 确保您的tcp服务器和tcp客户端应用程序都没有运行
  • 在Windows防火墙设置中删除应用的所有规则
  • 在CMD shell中运行以下命令 – 您需要使GREP可用:

    netstat -a -b | grep -e“27015” – after = 1

如果此命令的输出不为空 – 您将看到作为问题根源的应用程序的名称。 否则,尝试通过运行服务器然后 – 客户端来重现您的问题。 如上所述(或通过tcpview程序)通过netstat命令监视服务器的状态。 有趣的结果是什么。

Offtopic note:您的断开序列不完整。 谷歌graceful disconnect 。 通常它看起来像这样:

[ client ]发出shutdown (sd_send)并等待来自服务器的剩余数据

[ server ]如果recv ()== 0则{ send (剩余数据); 发出shutdown (sd_send); closesocket }

[ 客户 ]收到剩余数据; 如果recv ()== 0则关闭

在客户端中,您正在关闭发送连接:

 // shutdown the connection for sending since no more data will be sent // the client can still use the connectingSocket for receiving data iResult = shutdown(connectingSocket, SD_SEND); if (iResult == SOCKET_ERROR) { printf("shutdown failed: %d\n", WSAGetLastError()); closesocket(connectingSocket); WSACleanup(); return 1; } 

服务器检测到断开连接(recv返回0)并在不关闭其侧面连接的情况下完成,这就是您收到错误100054的原因。