3

在下面的代码中,我正在执行发送(23 字节),然后在无限循环中执行 recv,只要数据准备好(根据 select 调用的返回)。问题是我似乎总是从 recv() 中读取 1 个字节。我知道 TCP 是面向流的,并且不能保证我会返回什么大小,但是如果我启用我在下面禁用的代码(即在 while 循环中无限地执行 recv) - 我似乎总是读取 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 ; 
  }

}

.....

关于为什么会发生这种情况的任何想法?

4

2 回答 2

0

在注释掉的部分你有

rc = recv(m_sockfd, reply, 256, 0) ;

在你的选择中

if((rc = recv(m_sockfd, reply, sizeof(reply), 0)) == -1)

不确定 replay 的定义是否与 recv 相同,或者您将其作为参数传递。尝试在调用之前打印 sizeof(replay) 以查看实际上是 256。

于 2013-05-28T08:00:53.327 回答
-2

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

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

于 2013-05-28T22:53:16.647 回答