簡體   English   中英

recv 在套接字編程中是如何工作的?

[英]How does recv work in socket programming?

我試圖從高層次上理解 recv() 。 所以 recv 以“塊”的形式獲取數據,但我仍然不知道它是如何被精確處理的。 例子:

char buffer[1000]; 
int received= recv(sock, buffer, sizeof(buffer), 0)

這是否意味着如果我正在接收一個大文件,緩沖區,如果通過 sock 連接可能會反映它在接收變量中存儲了 500 個字節,然后在循環中接收另外 300 個字節,所有 800 個字節的數據將被存儲在循環結束時在緩沖區中(除非考慮到,否則丟失在接收到的變量中),或者緩沖區是否需要一個指針來跟蹤它上次接收數據的位置以將其存儲在下一次迭代中?

recv沒有上下文。 它只知道它有一些要寫入的地址(指針)和一些最大大小 - 然后它會嘗試這個。 它總是從給定的地址開始寫入。 例如,如果希望在某些先前接收到的數據之后添加數據,則可以簡單地將指針指向先前數據之后的位置,而不是緩沖區的開頭。 當然,應該調整允許讀取的最大大小以不溢出緩沖區。

您問“recv() 是如何工作的?”,因此可能值得簡要研究一個更簡單的 function ,它基本上做同樣的事情 - read()

recv()的操作方式與read() function 大致相同。 主要區別在於recv()允許您在最后一個參數中傳遞標志 - 但無論如何您都不會使用這些標志。

我的建議是 - 在嘗試使用recv()從網絡套接字讀取之前 - 在純文本文件上練習使用read()

兩個函數都返回讀取的字節數——除非出現錯誤,在這種情況下它們將返回 -1。 您應該始終檢查這種情況 - 並妥善處理。

這兩個函數也可以返回少於請求的字節數。 recv()的情況下 - 並從套接字讀取 - 這可能是因為另一端還沒有發送所有需要的數據。 在從文件讀取的情況下 - 使用read() - 這可能是因為您已到達文件末尾。

反正...

您將需要跟蹤緩沖區中的當前偏移量- 並在每次讀取時更新它。 所以聲明一個文件范圍的變量offset

static off_t offset; static char buffer[1000];

然后 - 當你的“循環”運行時 - 每次讀取后增加偏移量......

while (1) {
    size_t max_len = sizeof(buffer) - offset;
    ssize_t count = recv(sock, buffer+offset, max_len, 0);
    if (count == -1) {
        switch (errno) {
            case EAGAIN:
              usleep(20000);
              break;
            default:
              perror("Failed to read from socket");
              close(sock);
              break;
        }
    }
    if (count == 0) {
        puts("Looks like connection has been closed.");
        break;
    }
    offset += count;
    if (offset >= expected_len) {
        puts("Got the expected amount of data. Wrapping up ...");
    }
}

筆記:

  • 使用這種方法,您要么需要事先知道預期的數據量,要么使用特殊的分隔符來標記消息的結尾
  • max_len變量指示緩沖區中還剩下多少空間 - 並且(也許不用說)您不應該嘗試讀取比這更多的字節
  • recv()命令的目標是buffer+offset - 不是buffer
  • 如果recv()返回零,AFAIK 這表明另一端已執行“有序關閉”。
  • 如果recv()返回-1,你真的需要檢查返回碼。 EAGAIN不是致命的 - 只是意味着您需要再試一次。

暫無
暫無

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

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