簡體   English   中英

連續調用 recvfrom() 會丟失數據?

[英]Successive calls to recvfrom() loses data?

我正在開發一個使用 UDP 的可靠文件傳輸程序。 (計算機網絡課程。)

我的問題是 - 好吧,考慮一下這種情況:

  1. 發送者(例如)有 12 個字節的數據要發送。 所以發送者執行這個調用:

     sendto(fd, &buf, 12, 0, (struct sockaddr *)&cliaddr,sizeof(cliaddr));

    這會以不可靠的方式發送 12 個字節的數據。 該數據的前 4 個字節恰好是“消息長度”字段。 在這種情況下,前 4 個字節的值可能為 0x0000000C

  2. 接收方想要使用 recvfrom() 讀取前 4 個字節。 看到段大小是 12 字節,它想讀取剩余的 8 字節。 所以接收器可能看起來像這樣:

     /* read the segment size */ recvfrom(sockfd,&buf,4,0,(struct sockaddr *)&cliaddr,&len); /* do some arithmetic, use bzero(), etc */ /* read the rest of the data */ recvfrom(sockfd,&buf,8,0,(struct sockaddr *)&cliaddr,&len);

當我執行此代碼時,我可以毫無問題地接收前 4 個字節。 但是當我嘗試獲取剩余的數據時,這些數據似乎丟失了。 在我的 output 中,我得到了垃圾 - 看起來接下來的 12 個字節的一部分是發送者正在發送到()-ing。

這是預期的行為嗎? 也就是說,如果單個recvfrom()調用沒有讀取所有發送的數據,是不是不能保證數據(剩余的8個字節)可供我使用?

似乎發送段 header(包括其大小)和有效負載的標准方法不起作用。 這是否意味着我需要發送 2 個單獨的段 - 一個只包含 header 信息,然后是帶有有效負載的第二段? 還是我只是錯誤地使用了這些系統調用(或者是否有我缺少的標志或 setsockopt()?)

從 recv(2) 手冊頁:

如果消息太長而無法放入提供的緩沖區,則可能會丟棄多余的字節,具體取決於接收消息的套接字類型。

這就是發生在你身上的樣子。

您應該有一個最大消息大小的緩沖區並讀取該數量。 您將只讀取一個數據報並返回長度。 然后,您可以解析緩沖區前面的長度,並根據 recvfrom(2) 返回的內容對其進行驗證。

另一種方法是使用 MSG_PEEK 標志執行虛擬 recvfrom。 雖然返回的大小與您的緩沖區大小相同(或更多),但請獲取更大的緩沖區並重試。 然后再次執行 recvfrom(不帶 MSG_PEEK 標志)以從 UDP 緩沖區中刪除消息。

但是,當然,這是相當低效的,當您可以決定最大數據包大小時不應該這樣做。

暫無
暫無

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

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