簡體   English   中英

從套接字讀取時如何處理阻塞的 read() 調用?

[英]How to handle blocking read() call when reading from a socket?

我正在用 C 語言編寫一個簡單的 IRC 客戶端程序用於自學目的,並且在從套接字文件描述符調用讀取時無法理解read()函數的行為。

以下代碼片段工作並打印與運行相同的輸出

$ echo "NICK gertrudes\\r\\nUSER a 0 * d\\r\\n" | nc chat.freenode.net 6667

在終端中,這與我的程序到目前為止打印的相同:

while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) {
    printf("\nloop\n");
    buffer[n] = '\0';
    if (fputs(buffer, stdout) == EOF)
        error("fputs");
}
if (n < 0)
    error("reading from socket");

printf("out of the loop\n");

我不明白的是為什么程序永遠不會到達最后的printf調用,而是坐在那里,好像在等待來自服務器的更多信息。 這是否意味着最后一個回復長於 0 並且 IRC 服務器在我發送另一個命令之前不會發送任何新內容?

如果是這樣(在這里冒着跑題的風險),並且read()被阻塞,那么在程序等待該調用返回時,我應該在哪里編寫向服務器發送命令的邏輯?

我不明白的是為什么程序永遠不會到達最后的 printf 調用,而是坐在那里,好像在等待來自服務器的更多信息。

正在等待來自服務器的更多信息。 read()將在對等方斷開連接時返回零,而不是之前。

盡管您的程序尚未完成,但您還是錯誤地假設了幾件事。 讓我們在您的代碼中注釋這些。

while ((n = read(sockfd, buffer, sizeof(buffer)-1)) > 0) {
  • 如果你打算用一個\\0字節來完成它,那么讀sizeof(buffer)-1是好的,但認為你可以從套接字接收一個\\0 ,如果你想通用,不要假設你總是在讀文本。 許多安全漏洞來自這樣的錯誤。 程序員假設(錯誤地)數據是 ascii 文本,並且有人利用緩沖區溢出(事實並非如此)或其他非法內容,提供大量空字符使其失敗。

     printf("\\nloop\\n"); buffer[n] = '\\0'; if (fputs(buffer, stdout) == EOF)
  • 這是一個非常常見的錯誤……您習慣於看到,當您將\\n放在緩沖區的末尾時,stdio 會在看到最后一個緩沖區之前打印所有內容。 好吧,為此, stdio檢查描述符是否與終端關聯(通過ioctl(2)調用或isatty(3)調用)。 這不再適用於套接字,因此可能您的緩沖區已被復制到 stdio 緩沖區,並且 stdio 正在等待緩沖區填滿,或者您在調用write(2)之前使用fflush(3)顯式刷新緩沖區以發送所有數據在它上面。

     error("fputs");
  • 做一個fflush(stdout); 在這一點上,所以你確定你的所有數據都發送到對等點,然后再繼續,或者根本不使用 stdio(使用簡單的write(2)調用,直到你足夠熟練地准備一個select(2)的線程select(2)在套接字上准備好接受更多數據后立即提供更多數據)

     } if (n < 0) error("reading from socket"); printf("out of the loop\\n");

暫無
暫無

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

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