簡體   English   中英

C ++非阻塞套接字-等待所有recv數據

[英]C++ nonblocking sockets - wait for all recv data

我沒有在本地系統上遇到這個問題(當然),但是現在我正在設置虛擬服務器,所以我的部分代碼出現了問題。

為了從無阻塞TCP recv()接收所有數據,我有此功能

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;
}

我注意到recvAll 通常會打印RES: 1024 (1024是我發送的字節數),並且效果很好。 但是不經常出現數據丟失,它僅輸出RES: 400 (其中400是大於0且小於1024的某個數字),我的代碼不起作用,因為它期望所有1024個字節。

我也嘗試打印WSAGetLastError()並在調試中運行,但是由於打印/調試問題,程序運行得足夠慢,因此我沒有遇到此問題。

我認為此功能非常適合阻塞套接字,但不適用於非阻塞套接字。

關於測量的任何建議,我可以確保在非阻塞套接字上接收到所有1024個字節而不會丟失數據?

如果您使用非阻塞模式,那么您將讀取已經到達系統的所有數據。 讀出所有數據后,recv返回錯誤,原因取決於系統:

  • EWOULDBLOCK(在posix系統中)
  • Windows套接字系統中的WSAEWOULDBLOCK

收到此錯誤后,您需要等待其他數據的到達。 您可以通過以下幾種方式進行操作:

  • 等待特殊功能,例如選擇/投票/ epoll
  • 稍等片刻,然后嘗試再次接收(用戶空間輪詢)

如果需要減少延遲,請選擇/輪詢/ epoll。 睡眠要簡單得多。

另外,您還需要考慮TCP是流協議,並且不會保持成幀。 這意味着您可以發送例如256個字節,然后再發送另一個256個字節,但一次接收512個字節。 反之亦然:您可以一次發送512個字節,第一次讀取時接收256個字節,下次讀取時再接收256個字節。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM