2017-06-01 54 views
0

假設下面的代碼(爲簡單起見,我省略了必要的錯誤處理):我可以確定在成功調用recv與MSG_PEEK後立即執行的UDP recv不會被阻止嗎?

recv(sockfd, NULL, 0, MSG_PEEK); 
recv(sockfd, buff, bufflen, 0); 

在這種情況下,我可以肯定的是,第一次調用recv後整個數據報已經收到並因此第二個電話recv不會阻止?

或者它可以發生,如果IP拆分數據報,第一recv回報,只要該數據報的任何部分被接收,而第二recv將阻塞,直到接收到整個數據報?

如果我第一次調用替換到recv有:

recv(sockfd, NULL, 0, MSG_PEEK | MSG_TRUNC); 

我可以肯定地說,這隻會一次返回整個數據報被接收,因爲否則就沒有辦法爲recv可靠地返回整個數據報的長度,按照MSG_TRUNC的要求?

+1

如果在同一個套接字上有FD的另一個進程或線程,則不應該。在你做之前它可以讀取數據包。 – Barmar

回答

3

我可以肯定的是,第一個電話後,recv的整個數據報已經收到 ,因此第二次調用到的recv不會 塊?

UDP套接字以全數據報單元操作。第一次調用在數據報可用之前不會返回,除非它返回-1來指示錯誤。 (一個TCP套接字可能會返回0來表示連接的信號閉合,但這不會發生在UDP上,因爲它是無連接的。)

@Barmar在註釋中觀察到,另一個線程或訪問相同套接字的進程可能的原則,在等待的數據報之前讀取那個叫做第一個recv()的數據報,但如果這不是你所關心的,那麼後面的recv()確實應該返回整個數據報,直到緩衝區中可用的空間量(任何多餘的字節在該消息丟失)。當然這引出了你爲什麼要這樣做的問題 - 你可能會跳過第一個recv(),如果有必要的話,讓第二個阻止。

MSG_TRUNC添加到標誌不會改變上述任何情況。同樣,UDP套接字以全數據報單元操作。唯一的區別是返回值給你數據報的大小。 可能是額外撥打recv()的原因。

+0

爲什麼這樣的構造?我有兩個線程,一個重複執行'recv',另一個重複執行'send',唯一的目的是讓他們完成工作,而不必等到對方的阻塞套接字調用返回。爲了簡單起見,我想在互斥體下執行第二個'recv',以保護常用數據被鎖定,這樣第二個'recv'就可以寫入這個公共數據。如果第二個'recv'沒有阻塞,那就沒問題。如果它可以阻止,那麼整個想法就沒有多大意義。 – gaazkam

相關問題