2009-04-23 51 views
2

我正在第一次使用C++中的UDP套接字,並且我不確定我是否理解它們是如何工作的。我知道sendto/recvfromsend/recv通常會返回實際發送或接收的字節數。我聽說這個值可以任意小(但至少爲1),並且取決於套接字緩衝區(讀取時)的數據量或緩衝區中剩餘的空閒空間量(寫入時)。關於UDP/IP和sendto/recvfrom返回值的困惑

如果sendtorecvfrom只能保證每次發送或接收1個字節,並且數據報可以不按順序接收,那麼UDP協議如何保持一致?這不意味着當我收到消息時,消息中的字節可以隨意洗牌嗎?有沒有辦法保證郵件一次發送或接收?

回答

2

這是一個比那更強。 UDP確實提供了一個完整的包;緩衝區大小可以任意小,但必須包括在數據包中發送的所有數據。但也有一個大小限制:如果您想發送大量數據,則必須將其分解爲數據包並能夠自行重新組合。它也沒有保證交付,所以你必須檢查,確保一切都通過。

但是既然你可以用UDP實現所有的TCP,它就必須是可能的。

通常,你使用UDP做的是製作離散的小包。

隱喻地說,想想UDP就像發送明信片和TCP一樣打電話。當你發送明信片時,你不能保證交付,所以你需要做一些事情,比如確認回來。通過電話,您知道連接存在,並且您立即聽到答案。

1

不可以。用sendto發送數據包,可以包含一個字節。 如果您發送10個字節作爲單個sendto調用,這10個字節會被髮送到一個單獨的數據包中,這將會像您期望的一樣收到。

當然,如果你決定一個接一個地發送這10個字節,每個都有一個sendto調用,那麼的確發送和接收10個不同的數據包(每個包含1個字節),並且它們可以是任意的訂購。

這與通過郵寄服務發送圖書相似。您可以將整本書整體打包到一個盒子中,或者拆下每一頁,並將每一封作爲單獨的一封信發送出去。在第一種情況下,該軟件包較爲龐大,但您將該書作爲單個訂購實體收到。在後者中,每個包都很輕,但是運氣好的話可以讀取;)

1

實際上你可以發送一個0字節長的UDP數據報。所有發送的都是IP和UDP頭。另一端的UDP recvfrom()將返回長度爲0.與TCP不同,這並不意味着對等關閉了連接,因爲UDP沒有「連接」。

1

我有一個客戶端程序在專用於等待UDP套接字上的傳入數據的線程中使用阻塞選擇(NULL超時參數)。即使它被阻塞,選擇有時也會返回,表明單個讀描述符已經「準備就緒」。隨後recvfrom的返回0。

一些實驗後,我發現,在Windows至少,發送一個UDP包的端口,這不是期待它會導致在隨後的recvfrom的得到0字節的主機上。我懷疑某種拒絕通知可能來自另一端。我現在用這個提醒,我忘記了在查找客戶端傳入流量的服務器上啓動進程。

順便說一句,如果我不是「的sendto」有效但未被使用的IP地址,然後選擇並不如預期返回就緒狀態和塊。我還發現阻塞與非阻塞套接字沒有區別。