對於linux網路編程,我們都知道UDP是發送資料報,不是連線導向的協議,也就是它只是把資料報發送到鏈路層,至於能不能到達目的IP和連接埠,他都無能為力了。而且,我們只要在sendto函數中指定你要發送的連接埠和IP地址就可以了,我們不用綁定連接埠和IP。
但是,如果對UDP進行connect函數的調用,會發生什麼現象呢?
那麼,connect函數是串連外部的IP和連接埠,一般我們是串連伺服器的公用的連接埠和IP,但是,用戶端也可以的!
有了這個能力,我們可以分為兩個種:
1,未串連的UDP,新建立的UDP通訊端就是這樣的。
2,已串連的UDP,調用connect函數就是這樣的。
其中,已串連的畢未串連的多了三個變化:
1,我們再也不能給輸出操作指定目的IP和目的連接埠。也就是說,我們不能調用sendto,而是用write或者send。寫到UDP的緩衝區裡的資料,將自動發送到你調用connect指定的IP和連接埠。
2,我們不在是用recvfrom獲得資料報的寄件者,而改成了read,recv或者recvmsg。在一個已串連的通訊端上,核心由輸入操作返回的資料報只有那些來自connect所指定的協議地址的資料報。目的地為這個已串連的UDP通訊端的本地協議地址(IP和連接埠),發源地卻不是該通訊端早先connect到得協議地址的資料報,不會投遞到該通訊端。這樣就限制了已串連的UDP通訊端能且只能與一個對端交換資料報。
3,由已串連的通訊端引發的非同步錯誤發回給他們所在的進程,而未串連的UDP通訊端不接受任何非同步錯誤。
但是,我們如果對一個UDP多次調用connect會發生什麼情況?
我們得確定為什麼我們需要對一個一個UDP多次調用connect?不外乎這兩個情況:
1,制定新的IP和連接埠。
2,中斷連線。
第一個目的不同於TCP串連connect的使用:對於TCP串連,connect只能調用一次。
為了斷開一個已串連的UDP串連,我們再次調用connect時,把通訊端地址結構的地址簇成員(IPv4為sin_family,IPv6為sin6_family),設定為AF_UNSPEC。這麼做可能會返回一個EAFNOSUPPORT錯誤(Address family not supported by protocol ),但是沒有關係。使通訊端斷開的串連的是在已串連的UDP通訊端上調用connect的進程。
效能:
當讀者給未串連UDP調用sendto的時候,發送超過兩個資料報時,核心執行這六個步驟:
1,串連通訊端。
2,輸出第一個資料報。
3,斷開通訊端串連。
4,串連通訊端。
5,輸出第二個通訊端。
6,發送第二個資料報。
當讀者給已串連的UDP先後兩次調用write時,核心執行以下三個步驟:
1,串連通訊端。
2,輸出第一個通訊端。
3,輸出第二個通訊端。
在這棟情況下,核心就複製一次含有目的IP地址和連接埠號碼的通訊端地址結構,相反調用兩次sendto時,則要複製兩次。
臨時串連未串連的UDP,需要消耗三分之一的開銷。