首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

Linux Socket 程式設計:select + recv 返回值與 while(recv) 差異分析

     編輯:程式設計綜合問答

程式碼對比


// 分支 1:單次 recv
if (select(...) > 0) {
    nlen = recv(sockfd, buf, 199, 0); // 返回實際讀取位元組數
}

// 分支 2:while 迴圈
while ((nlen = recv(sockfd, buf, 199, 0)) > 0) {
    // nlen 總是 1?
}

現象解釋

  • 分支 1:select 就緒後,recv 讀取緩衝區所有可用資料(最多 199 位元組),返回實際長度(如 199)。
  • 分支 2:while 迴圈**每次只讀 1 位元組**?否。實際上 recv 仍會讀取所有可用資料。但觀察到 nlen=1 可能原因:
    • 發送端每次 send 只發 1 位元組(Nagle 演算法或應用層邏輯)。
    • 接收緩衝區極小(SO_RCVBUF=1)。
    • **關鍵 Bug**:buf 指標未重設,pcBuffer += nlen 導致後續 recv 寫入越界記憶體,行為未定義。

正確接收迴圈模式


int total = 0, expected = 199;
while (total < expected) {
    int n = recv(sockfd, buf + total, expected - total, 0);
    if (n <= 0) { /* 錯誤/關閉 */ break; }
    total += n;
}
// 此時 total 為完整訊息長度

select 返回值處理


fd_set readfd;
FD_ZERO(&readfd);
FD_SET(sockfd, &readfd);
struct timeval tv = {5, 0}; // 5 秒超時
int ret = select(sockfd + 1, &readfd, NULL, NULL, &tv);
if (ret > 0 && FD_ISSET(sockfd, &readfd)) {
    // 可讀,執行上述接收迴圈
}

總結

while(recv()) 觀察到返回 1 多半是發送端逐位元組發送或接收緩衝區指標管理錯誤。正確做法:預期長度循環讀取、指標偏移累加、檢查返回值 <=0 處理斷線/錯誤。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved