簡單分析一下socket中的bind

在最開始接觸bind的時候,只是在寫基於tcp的server端的時候,知道在listen之前需要先bind一下,用來確保socket能在某個固定的端口監聽。而bind的時候,函數參數中的端口填自己將要綁定的端口就行;而IP地址,需要填本機的IP,但是也可以用一個宏INADDR_ANY代替,用這個宏就可以不用查找本機的IP,它就可以代替本機的IP。當時只覺得這個INADDR_ANY比較神奇,但是由於當時覺得用起來很方便,也沒出啥問題,也就沒有再深究。
  但是最近在做RTSP服務器的時候,有種特殊的應用,導致我不得不對bind這個函數仔細地看一下。
  我們知道無論是UDP還是TCP,socket都會與一個本地的IP和端口想對應,我們往往把這個IP和端口稱之爲socket的源地址和源端口。當我們作爲客戶端利用socket去發送數據時,很少會去考慮這個源地址和源端口到底是什麼,我們更關心的是它的目的地址和端口。我們往往只有在監聽的時候,纔去考慮這個源端口,所以我們在監聽的時候會去用bind。當我們bind之後,內核就會將這個socket的源端口鎖定到我們設定的端口上。但是這就有一個問題,這個bind綁定端口,是將本來沒有源端口的socket綁定到我們指定的端口上,還是將一個已經分配了端口的socket重定向到我們指定的端口上呢?
  在《UNIX網絡編程》這本書中提到:“如果一個TCP客戶或者服務器未曾調用bind捆綁一個端口,當調用connect或listen時,內核就要爲相應的套接字選擇一個臨時接口。”從這句話中可以判斷出,其實在調用socket函數創建socket時,內核還並未給socket分配源地址和源端口。而對於UDP,我猜測在調用sendto發送數據時,在未捆綁端口的情況下,內核也會隨機分配端口。
  而我遇到的特殊應用要求我在用UDP發送數據之前要告訴對方我的發送端口,這也就意味着我在sendto之前必須要捆綁端口,因此我在發送數據之前就得調用bind函數綁定一下端口了。但是我就在想內核既然有隨機分配端口的能力,而我需要的也只是讓它綁定一下而不用綁定在固定端口的業務,socket中應該能夠提供這種業務。然後果然我發現bind就具備這種能力,當bind的參數中端口地址爲0的時候,這時候就是由內核分配端口。這樣我就不用考慮端口地址重複的問題,而放心的把這個問題交給內核處理了。
  就在發現bind的這個機制的同時,我發現其實bind對於源地址也同樣具備這種處理方式,當系統具有多IP(多網卡)的情況,當我們把bind函數中的ip參數置0時,就是由內核自己選擇分配IP。而之前一直覺得很神奇的INADDR_ANY其實一點也不神奇,它的值其實就是0。所以當我們只有單一IP的時候,我們就可以用INADDR_ANY去代替那個單一的IP,因爲內核分配的時候只能選擇這一個IP。從而造成了INADDR_ANY就是本機IP的現象。

 

轉自: http://www.cnblogs.com/nightwatcher/archive/2011/07/03/2096717.html

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章