天天看點

Linux Socket學習--面向非連接配接的協定

面向非連接配接指的是通信之前不需要建立連接配接,我們生成了一個非連接配接的套接口,就可以向任何願意接受我們消息的套接口發送消息,而且每一個消息都可以被重定向到不同的套接口。

我們之前的文章中提供socketpair函數,但是我們當時沒有說這個函數是使用面向連接配接協定來生成套接口對的。

sendto()函數介紹

    sendto函數容許我們寫一個資料報,并且同時制定接受者的位址。文法如下:

如果函數調用成功,傳回值就是發送的位元組數,如果調用失敗,傳回值就是-1.我們可以通過檢查errno的值來判斷錯誤的原因。

雖然在大多數的情況下,參數flags隻需要為0,但是我們還是列出了其他的值:

<a href="http://images.cnblogs.com/cnblogs_com/rollenholt/201208/201208202150235294.png"></a>

recvfrom函數介紹

recvfrom函數使得我們能夠在接受資料報的同時,也能夠得到發送者的位址,函數文法如下:

函數調用成功的話傳回接受緩沖區所接受的位元組數,如果調用失敗,傳回值為-1.我們可以通過檢查errno的值來判斷錯誤的原因。

    注意:如果使用函數recvfrom來接受不同的協定的資料報,那麼我們就必須确定為所有可能遇到的位址族配置設定足夠的套接口位址空間。比如位址族AF_INET和AF_LOCAL套接口位址的尺寸就不一樣,通常我們可以使用c語言中的聯合資料結構來解決這個問題。

   下表是recvfrom參數的flags的取值,不過通常情況下我們僅僅取值為0:

<a href="http://images.cnblogs.com/cnblogs_com/rollenholt/201208/201208202150247114.png"></a>

下面我們來編寫一個UDP資料報伺服器程式:

--UNDONE(此處代碼有待添加)

下面這個程式是UDP用戶端程式:

如果我們在不啟動伺服器程式的情況下,僅僅啟動用戶端程式,我們會發現用戶端程式可以啟動,也可以生成套接口并且要求輸入,甚至函數dendto的調用也是成功的,錯誤來源于recvfrom,這個說明了,發送一個資料報僅僅是将資料報發送出去,但并不能說明他已經被成功接收。

  在上面的例子中大家可能注意到用戶端程式在生成套接口之後,并沒有調用bind函數,我們知道bind函數的作用就是限制用于進行網絡通信的接口,在上面的例子中省略了對bind的調用,意味着程式可以選擇任何一個接口進行發送,在效果上就如同套接口被綁定了統配套接口位址,當程式相應的時候,他也可以使用結果任何一個接口來接收資料。這個時候,套接口的端口号也是通配的。

我們也可以使用bind函數明确的指出通配位址,我們可以通過INADDR_NONE來達到目的,另外為了得到一個通配的端口号,可以将端口号指定為0.是以指定IP位址和端口号分别為INADDR_NONE和0所達到的效果和不調用bind函數的效果是相同的。

現在遇到的問題是如果用戶端程式的位址和端口号都是通配的,那麼伺服器怎麼向這個套接口進行應答呢?答案是:IP位址和端口号是資料報在發送的時候才配置設定的。通配端口号是從目前所有可用的端口号中随機挑選的。

如果發送主機具有多個接口,而且又發送了一個資料報,那麼這個資料報的原始IP位址就可能變化,總之,原始IP位址反應的是發送資料報所使用的網絡接口的IP位址。

==============================================================================

本文轉自被遺忘的部落格園部落格,原文連結:http://www.cnblogs.com/rollenholt/archive/2012/08/20/2648143.html,如需轉載請自行聯系原作者

繼續閱讀