2010-08-26 92 views
6

我在Windows上使用阻塞C套接字。 我使用它們將來自服務器的數據更新發送到客戶端,反之亦然。我發送頻率更高(每100ms)。 send()函數是否會等待接收方recv()在結束之前接收數據?C socket:是否等待recv結束?

我認爲不是我的理解以及手冊頁:

「發送成功完成()並不能保證郵件的傳遞。」

如果一個正在運行10個send() OCCURENCES而另一隻具有完整的1 recv()那麼會發生什麼?

我是否需要使用某種確認系統?

+0

什麼是套接字的協議類型? TCP,UDP還有其他的東西? – torak 2010-08-26 19:18:09

+0

我使用TCP協議 – Giann 2010-08-26 19:44:24

回答

10

讓我們假設您使用的是TCP。當您呼叫發送時,您發送的數據立即被放置在傳出隊列中併發送,然後成功完成。但是,如果發送無法將數據放在傳出隊列上,發送將返回一個錯誤。

由於Tcp是一種有保證的傳送協議,只有在遠程端收到確認後才能刪除傳出隊列上的數據。這是因爲如果沒有及時收到數據,可能需要重新發送數據。

如果遠端緩慢,傳出隊列將填滿數據,然後發送將阻塞,直到有足夠空間將新數據放在傳出隊列中。

但是,連接可能失敗,以至於無法發送任何其他數據。雖然一旦TCP連接關閉,任何進一步的發送都會導致錯誤,但用戶無法知道實際上到達另一端的數據量。 (我知道沒有辦法從套接字檢索TCP簿記到用戶應用程序)。因此,如果需要確認收到數據,則應該在應用程序級別實現此功能。

對於UDP,我認爲不言而喻,某種報道已經或尚未收到的內容是必須的。

7

send()阻塞,直到操作系統(內核)取得數據並將其放入傳出數據的緩衝區。它不會等到另一端收到數據。

0

如果你使用的是TCP,你可以免費得到確認,因爲這是協議在底層做的一部分。但聽起來像這種類型的應用程序,你可能會想使用UDP。在這兩種情況下,雖然send()不會阻止,直到客戶端成功recv()

如果客戶端收到每條消息至關重要,那麼請使用TCP。如果客戶端可能錯過一條或多條消息,則使用UDP。

+1

您可以在TCP層上進行配置,但是如果您需要在應用層上進行配置,那麼這並不會對您有所幫助,例如,如果您需要知道已收到消息,則需要在任何應用程序中實施ack你正在使用的協議。 – nos 2010-08-26 19:34:37

2

如果您是通過TCP發送的,您將獲得有保證的遞送,另一端將按照發送的順序接收數據。但是,這可能會被合併在一起,因此作爲單獨的大數據包可以接收作爲10個單獨更新發送的數據(反之亦然 - 可以在任意數量的數據包中打破單個更新)。這意味着,除其他外,任何數據的任何ACK都隱式確認接收到所有先前的數據。

如果您使用的是UDP,那麼這些都不是真的 - 數據可能不按順序到達,或者被丟棄,並且根本不會傳送。如果你關心所有收到的數據,你只需要在UDP本身之上建立你自己的確認系統。

當然,還有對擔保的限制 - 如果網絡電纜被削減(或其他)數據包將不會被髮表,但你至少可以得到一個錯誤信息,告訴您連接丟失了。

0

TCP保證在較低的TCP堆棧級別下交付。它重試交付,直到接收部分承認數據已收到,但您的應用程序可能永遠不知道這一事實。

假設您正在發送數據塊,並且需要根據某種邏輯將這些數據塊放在某處。如果您的應用程序不準備知道每個塊的放置位置,則在TCP級別接收它可能沒有用處。原帖是關於應用程序級別的邏輯。