В моем коде ниже я делаю send (23 байта) и затем в бесконечном цикле while выполняю recv всякий раз, когда данные готовы (согласно возврату из вызова select). Проблема в том, что я всегда получаю 1 байтовое чтение из recv (). Я понимаю, что TCP ориентирован на поток, и нет никакой гарантии, какой размер я получу обратно, но если я включу код, который я отключил ниже (то есть сделаю recv в цикле while), — мне всегда кажется, что читать 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)
нет уверенности, что определение воспроизведения является той же функцией, что и recv, или вы передали его в качестве параметра. Попробуйте напечатать sizeof (replay) перед вызовом, чтобы увидеть, что на самом деле это 256.
однажды Выбрать() информирует вас о доступных данных, вы должны позвонить принимаем () а затем определить новый сокет для фактического чтения этих данных.
Итак, вы можете думать о Выбрать() как «ушная раковина». Как только «ухо» что-то слышит, оно создает еще один сокет, предназначенный для отправки-получения TCP-потока между вами и «слышащей» удаленной стороной. Как только удаленная сторона больше не доступна, вы должны закрыть эту розетку. В то же время «ушной» сокет сохраняется до тех пор, пока вы не будете заинтересованы в обслуживании входящих запросов на соединение.