C++ nonblocking sockets - wait for all recv data

痞子三分冷 提交于 2021-02-10 11:49:06

问题


I wasn't running into this problem on my local system (of course), but now that I am setting up a virtual server, I am having some issues with a part of my code.

In order to receive all data from a nonblocking TCP recv(), I have this function

ssize_t Server::recvAll(int sockfd, const void *buf, size_t len, int flags) {
    // just showing here that they are non-blocking sockets
    u_long iMode=1;
    ioctlsocket(sockfd,FIONBIO,&iMode);

   ssize_t result;
   char *pbuf = (char *)buf;
   while ( len > 0 ) {
     result = recv(sockfd,pbuf,len,flags);
     printf("\tRES: %d", result);
     if ( result <= 0 ) break;
     pbuf += result;
     len -= result;
   }

   return result;
}

I noticed that recvAll will usually print RES: 1024 (1024 being the amount of bytes I'm sending) and it works great. But less frequently, there is data loss and it prints only RES: 400 (where 400 is some number greater than 0 and less than 1024) and my code does not work, as it expects all 1024 bytes.

I tried also printing WSAGetLastError() and also running in debug, but it looks like the program runs slow enough due to the print/debug that I don't come across this issue.

I assume this function works great for blocking sockets, but not non-blocking sockets.

Any suggestions on measurements I can take to make sure that I do receive all 1024 bytes without data loss on non-blocking sockets?


回答1:


If you use non-blocking mode then you read all data that has already arrived to the system. Once you read out all data recv returns error and reason is depending on system:

  • EWOULDBLOCK (in posix system)
  • WSAEWOULDBLOCK in windows sockets system

Once you receive this error you need to wait arrival of another data. You can do it in several ways:

  • Wait with special function like select/poll/epoll
  • Sleep some time and try to recv again (user-space polling)

If you need to reduce delay select/poll/epoll is preferable. Sleep is much more simple to implement.

Also you need consider that TCP is stream protocol and does NOT keep framing. This means that you can send, for example, 256 bytes then another 256 bytes but receive 512 bytes at once. This also true in opposite way: you may send 512 bytes at once and receive 256 bytes with first read and another 256 bytes in next read.



来源:https://stackoverflow.com/questions/47975612/c-nonblocking-sockets-wait-for-all-recv-data

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!