Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/137.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 使用select()返回1字节读取的TCP Recv_C++_Sockets_Select_Recv - Fatal编程技术网

C++ 使用select()返回1字节读取的TCP Recv

C++ 使用select()返回1字节读取的TCP Recv,c++,sockets,select,recv,C++,Sockets,Select,Recv,在下面的代码中,我将执行send23字节,然后在无限while循环中,每当从select调用返回的数据读取时,我将执行recv。问题是,我似乎总是从recv得到1字节的读取。我知道TCP是面向流的,并且不能保证返回的大小,但是如果我启用了下面禁用的代码。在一段时间内做一个记录循环——我似乎总是按照我的预期读29字节。但是,如果使用select函数调用,recv在每次迭代中只读取1字节。当它读取完所有数据时,它可能会一直这样做 int rc = 0, numBytes=0 ; char re

在下面的代码中,我将执行send23字节,然后在无限while循环中,每当从select调用返回的数据读取时,我将执行recv。问题是,我似乎总是从recv得到1字节的读取。我知道TCP是面向流的,并且不能保证返回的大小,但是如果我启用了下面禁用的代码。在一段时间内做一个记录循环——我似乎总是按照我的预期读29字节。但是,如果使用select函数调用,recv在每次迭代中只读取1字节。当它读取完所有数据时,它可能会一直这样做

 int rc = 0, numBytes=0 ; 
 char reply[256] ; 

 // Send a ping
 char PingPacket[23] ; 

 PreparePingPacket(PingPacket) ; 
 numBytes = send(m_sockfd,PingPacket,23,0); 

/*----- COMMENTED OUT
while(1){
  rc = recv(m_sockfd, reply, 256, 0) ;
  if(rc == -1)
  {
    fprintf(stderr, "Error on Sending Ping .. \n") ;   
    return ; 
  }else{
    ParsePacket(reply, rc) ; 
  }
}
*/ END OF COMMENTED PART

// Now wait for all types of pongs to come back
fd_set rfs ; 
while(1)
{
  memset(reply,'\0',256) ; 

FD_ZERO(&rfs) ;

FD_SET(m_sockfd,&rfs) ; 

// Wait for ever .. 
if((rc = select(m_sockfd+1, &rfs, NULL, NULL, NULL)) < 0)
{
  fprintf(stderr, "Select Error after connection .. \n") ; 
  close(m_sockfd) ; 
  return ;
}

if(FD_ISSET(m_sockfd, &rfs))
{
  cout << "Read. for reading" << endl ; 
  int rc = 0 ; 
  if((rc = recv(m_sockfd, reply, sizeof(reply), 0)) == -1)
  {
    cout << "Could not read anything .... " << endl ;   
    fprintf(stderr,"Error: %d\n",errno) ; 
    return ; 
  }
  else if(rc == 0)
  {
    cout << "The other side closed the connection. \n" << endl ; 
  }

}

.....

你知道为什么会这样吗

在已注释掉的部分中

rc = recv(m_sockfd, reply, 256, 0) ;
在“选择”对话框中

if((rc = recv(m_sockfd, reply, sizeof(reply), 0)) == -1)
不确定replay的定义是与recv相同的函数,还是作为参数传递。尝试在调用之前打印sizeofreplay,查看其实际值为256。

一旦select通知您可用数据,您必须调用accept,然后确定一个新套接字以实际读取该数据


因此,您可以将select视为耳塞。一旦耳朵听到了什么,它就会创建另一个专用于在您和听到的远程方之间发送接收TCP流的套接字。一旦远程方不再可用,您必须关闭该套接字。同时,耳塞一直存在,直到您对传入的连接请求感兴趣。

开始时,停止混合C样式的STDIO函数,如FPROTF和C++流输出。用一个或另一个。如果要打印到标准错误,则使用std::cerr。至于您的问题,使用select只能保证您可以在不阻塞的情况下调用例如recv,对于可用的字节数没有任何保证。您还应该记住,TCP不能保证您能够在一次recv调用中获取所有数据,您可能需要多次调用它才能获取所有数据,如果套接字阻塞,这当然可能会有问题。此外,您可以显示回复声明吗?添加了回复声明。您可以使用非阻塞套接字并在循环中读取,直到获得整个数据包。除此之外,您的代码没有问题。通过打印验证为256。仍然是相同的结果。只有在设置为侦听的套接字上调用select时,这才是正确的。这里的情况似乎并非如此。