C++套接字选择和接收问题

C++套接字选择和接收问题,c++,select,sockets,recv,C++,Select,Sockets,Recv,下面是我在套接字编程方面遇到的问题代码片段。在这里,在select调用之后,若我并没有在第9行设置睡眠,在Windows XP上,第11行接收到1字节,而从服务器发送的4字节是整数,当我检查xmlSize时,它被设置为0。由于iResult为1,执行将继续,并在第15行上使用xmlSize=0调用receive,并且iResult设置为0,因为iResult=0连接已关闭 但在Windows7上,这并没有发生,程序愉快地读取了4个字节并继续正常执行。在XP上,我放了一个sleep,我只是编造了这

下面是我在套接字编程方面遇到的问题代码片段。在这里,在select调用之后,若我并没有在第9行设置睡眠,在Windows XP上,第11行接收到1字节,而从服务器发送的4字节是整数,当我检查xmlSize时,它被设置为0。由于iResult为1,执行将继续,并在第15行上使用xmlSize=0调用receive,并且iResult设置为0,因为iResult=0连接已关闭

但在Windows7上,这并没有发生,程序愉快地读取了4个字节并继续正常执行。在XP上,我放了一个sleep,我只是编造了这个,它工作了,但是为什么

此代码中的缺陷是什么

1   while(is_running())
2   {
3       FD_ZERO(&readfds);
4       FD_SET(server_socket, &readfds);
5       iResult = select(server_socket+1, &readfds, NULL, NULL, &tv);
6       if  (!(iResult != SOCKET_ERROR && FD_ISSET(server_socket, &readfds) )) {
7           continue;
8       }
9       Sleep(500); // This Sleep is not required on Windows 7, but is required on 10 XP but WHY? 
11      iResult = recv(server_socket, (char *)&xmlSize, sizeof(xmlSize), 0);
12      xmlSize = htonl(xmlSize);
13      if ( iResult > 0 ){
13          printf("Bytes received: %d, XML Size:%d", iResult, xmlSize);
14          
15          iResult = recv(server_socket, xml, xmlSize, 0);
16          if ( iResult > 0 ){
17              xml[xmlSize] = '\0';
18              printf("Bytes received: %d", iResult);              
19              operation_connection(xml);
20          }
21          else if ( iResult == 0 ){
22              printf(LL_INTERR, CLOG("Connection closed"));
23              break;
24          }
25          else{
26              printf("recv failed with error: %d", WSAGetLastError());
27              break;
28          }
29      }
30      else if ( iResult == 0 ){
31          printf(LL_INTERR, CLOG("Connection closed"));   
32          break;
33      }
34      else{
35          printf("recv failed with error: %d", WSAGetLastError());
36          break;
37      }
38  }

如果这是一个TCP套接字,您不应该在意。套接字传递一个流,它不以任何方式或方式对应到另一端的原始写入的大小

它可以将一兆字节作为一百万个1字节的读取,或者作为一个1MB的读取,或者两者之间的任何组合

如果您依赖于TCP连接所传递数据块的大小,那么您就做错了

如果您需要某种消息分隔符,那么在协议中显式设计一种,例如HTTP使用回车+换行符的方式。如果您的协议是ASCII,因此无法使用这些特定字节来分隔消息,则有两种经典方法:

使用其他字节序列,比如ASCII 0x1E,记录分隔符。 当CR+LF包含在消息中时,使普通的CR+LF用作分隔符。如果您的协议想要文本化,这将是更好的解决方案。
另一种方法是显式编码流本身中每条消息的长度,最好是作为前缀,以便您知道需要多少数据。

请参阅此其他so问题以获取答案和代码示例:


您知道,不能保证对recv的单个调用接收的字节数与要发送的单个调用发送的字节数匹配?好的,我现在看到了问题,但我没有预料到这种行为,因为recv函数将字节数作为参数。那么你能建议什么呢?这个数字是最大字节数,所以继续调用recv并调整这个数字,直到你读取了四个字节。是的,我确实依赖于块,但是像but CR或LF这样的分隔符对我来说不是一个选项,因为我的消息包含CR LF。那么你能建议另一种方法吗?如果不能使用分隔符,那么使用包含魔术和数据大小的标题是一种常用的技术。标头可以包含不同的字段,如消息类型、消息id等,。。。