簡體   English   中英

C socket原子無阻塞讀取

[英]C socket atomic non-blocking read

我正在實現一個TCP / IP服務器應用程序,該應用程序在邊緣觸發模式下使用epoll並執行無阻塞套接字操作。 客戶端使用沒有epoll的簡單阻止操作。

我看不到如何在服務器端實現“原子讀取”。 為了解釋我對“原子讀取”的含義,請參見帶有簡單阻塞操作的示例:

  • 客戶端和服務器都使用64K緩沖區。 (在應用程序級別。它們不會更改內核級別的套接字緩沖區。)
  • 客戶端通過一次寫入操作即可寫入12K數據。
  • 服務器讀取它。 在這種情況下,當緩沖區相同時,它將始終讀取整個12K。 因此它不能只讀取一半。 這就是我所說的“原子”。

但是在epoll +非阻塞操作的情況下,可能會發生以下情況:

  • 客戶端和服務器都使用64K緩沖區。 (在應用程序級別。它們不會更改內核級別的套接字緩沖區。)
  • 客戶端通過一次寫入操作即可寫入12K數據。
  • 6K到達服務器
  • epoll告知應用程序數據已到達套接字
  • 應用程序使用非阻塞操作將6K讀入緩沖區。
  • 重復讀取時,它將返回EAGAIN / EWOULDBLOCK。

在這種情況下,讀取的內容不是“原子的”。 不保證當通過單個寫操作寫入數據時,讀取將一次返回整個數據。

是否可以知道數據何時是部分數據? 我知道一種解決方案是始終將數據大小附加到開頭,或者另一種解決方案是始終關閉並重新打開連接,但是我不想這樣做:因為我認為內核必須知道不是完整的因為它保證了阻塞操作的原子性,所以“程序包”(該單元如何稱為BTW?)到來了。

非常感謝!

TCP是基於流的,而不是面向消息的。 即使在阻塞套接字的情況下,也不能保證應用程序發送的消息一勞永逸。 TCP將決定自己的路線。

因此,由應用程序對其“希望”進行“原子”讀取。 例如:

應用協議應規定消息應以長度字節為前綴。 長度字節通知對等體感興趣的應用程序數據的大小。 當然,應用程序應該知道兩字節長度指示符何時開始。

[2字節的味精長度] [感興趣的數據字節]

基於此信息,正在讀取的應用程序應采取措施。 它應該輪詢套接字,直到接收到所有由msg長度字節指示的字節為止。 只有這樣才能處理數據。

如果需要“原子”讀取而不是部分讀取,則可以在recv使用MSG_PEEK標志。 這不應從套接字緩沖區中刪除數據。 應用程序窺探套接字,根據返回值查看套接字緩沖區中是否需要所需數據數。

ret = recv(sd, buf, MAX_CALL_DATA_SIZE, MSG_PEEK);

暫無
暫無

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

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