2012-11-09 85 views
4

我試圖通過recvfrom接收數據包的一部分。實際上,它的工作原理是這樣的:通過recvfrom(UDP)接收數據包的一部分

recvfrom(sockfd, serialised_meta, 12, flags, src_addr, addrlen); 
recvfrom(sockfd, serialised_buf, BUFLEN, flags, src_addr, addrlen); 

的數據是這樣的發送:

bufd->Serialise(serialised_buf, BUFLEN+12); 
sendto(sockfd, serialised_buf, BUFLEN+12, flags, dest_addr, addrlen); 

這樣的想法是,先讀一些元數據,然後決定是否接受其他的東西。問題是,如果第二個緩衝區(serialised_buf)在開頭,我會收到4'/ 0'字節。它似乎不是序列化問題,我之前使用過序列化,並且一切都很酷,而我一次收到整個數據包(元數據和數據)。 關於如何修復它的任何想法?

PS。我知道我可以跳過不必要的字節)但無論如何,爲什麼它可能會發生?

回答

10

UDP不是「流」協議......一旦你做了初始recvfrom,數據包的其餘部分將被丟棄。第二個recvfrom正在等待下一個數據包...

+0

好的,那我的解決方案怎麼可能呢?這只是出於好奇)。如果數據包的剩餘部分被丟棄,則第二個recvfrom應該可以工作。提前致謝! 現在,我想,首先獲取meta的最好方法是使用peek標誌? – Roman

+0

如果你正在談論數據包的長度,你可以通過使用帶'FIONREAD'的'ioctl'來確定。你可以使用'MSG_PEEK',但是我不會打擾,除非你的數據包數據很大,而你的元數據很小......可能最好只跳​​過'ioctl'並且完全掃描並且具有最大緩衝區大小(對於你的應用程序)準備好去跳過/放棄數據。 – mark

3

UDP對消息進行操作,而不是像TCP那樣的數據流。使用UDP時,sendto()recvfrom()之間存在一對一的關係。沒有選項可以接收UDP中的部分數據,它是一種全有或全無的傳輸方式。您必須一次性完成整個BUFLEN+12消息,然後決定是否要實際使用它。這就是UDP的工作方式。

+0

它真的是一下子還是一無所有?我記得在某個地方應該經常檢查'recvfrom()'的返回值,將它與預期的大小進行比較,然後重複調用'recvfrom'直到所有的數據都被接收到。不幸的是,我不記得我在哪裏閱讀。如果這是無意義的,它會讓我的生活變得更輕鬆;) – user463035818

+0

......我所描述的只是TCP所需要的,而不是UDP所必需的?我找到了一個網站,他們描述了TCP的這條線(不是我所指的那個,但或多或​​少都是相同的技術:http://www.binarytides.com/receive-full-data-with-recv -socket-function-in-c /) – user463035818

+1

@ tobi303這就是TCP中發生的事情,而不是UDP中發生的事情。儘管返回值確實是讀取的字節數,但如果提供的緩衝區太小而無法接收整個消息,則UDP中的recvfrom會盡可能多地填充緩衝區,丟棄剩餘的未讀數據並報告一個EMSGSIZE '錯誤。所以你只有一次機會收到完整的信息。 –