原因: 1、 因為伺服器是時時在監聽有沒有客戶端的連線,如果伺服器不繫結IP和埠的話,客戶端上線的時候怎麼連到伺服器呢,所以伺服器要繫結IP和埠,而客戶端就不需要了,客戶端上線是主動向伺服器發出請求的,因為伺服器已經綁定了IP和埠,所以客戶端上線的就向這個IP和埠發出請求,這時因為客戶開始發資料了(發上線請求),系統就給客戶端分配一個隨機埠,這個埠和客戶端的IP會隨著上線請求一起發給伺服器,服務收到上線請求後就可以從中獲起發此請求的客戶的IP和埠,接下來伺服器就可以利用獲起的IP和埠給客戶端迴應訊息了。 2、採用UDP通訊 1)若有客戶端和伺服器之分的程式,建立sock後即可在該socket上用recvfrom/sendto方法傳送接受資料了,因為客戶端只需要用sendto傳送資料到指定的地址,當然若是bind了,程式也沒什麼問題,區別就是系統用預設自動bind()指定你自己的socket引數地址(特別是在指定特定埠的UDP對等通訊)只是這種情況沒有這樣用的。 那UDP伺服器是怎麼知道客戶端的IP地址和UDP埠? 一般來說有兩種方式: 一種是客戶端發訊息顯式地告訴伺服器IP地址和埠,訊息內容就包括IP地址和UDP埠。 另外一種就是隱式的,伺服器從收到的包的頭部中得到包的源IP地址和埠。 2)若是沒有客戶端和伺服器之分的程式,即自己指定特定埠的UDP對等通訊,則客戶端和伺服器都需要bind()IP地址和埠了。 通常udp服務端根本不需要知道客戶端的socket,它直接建立一個socket用於傳送即可,udp通訊的關鍵只在於IP和埠。 多個客戶端如果需要點到點分發,必須給服務端socket迴圈設定每個客戶端的IP併發出,但更常用的是廣播分發,服務端socket設定一個X.X.X.255的廣播地址並始終向它傳送,每個客戶端建立的socket只需要繫結這個廣播地址便可以收到。 客戶端用不用bind 的區別 無連線的socket的客戶端和服務端以及面向連線socket的服務端透過呼叫bind函式來配置本地資訊。使用bind函式時,透過將my_addr.sin_port置為0,函式會自動為你選擇一個未佔用的埠來使用。 Bind()函式在成功被呼叫時返回0;出現錯誤時返回"-1"並將errno置為相應的錯誤號。需要注意的是,在呼叫bind函式時一般不要將埠號置為小於1024的值,因為1到1024是保留埠號,你可以選擇大於1024中的任何一個沒有被佔用的埠號。 有連線的socket客戶端透過呼叫Connect函式在socket資料結構中儲存本地和遠端資訊,無須呼叫bind(),因為這種情況下只需知道目的機器的IP地址,而客戶透過哪個埠與伺服器建立連線並不需要關心,socket執行體為你的程式自動選擇一個未被佔用的埠,並通知你的程式資料什麼時候開啟埠。(當然也有特殊情況,linux系統中rlogin命令應當呼叫bind函式繫結一個未用的保留埠號,還有當客戶端需要用指定的網路裝置介面和埠號進行通訊等等) 總之: 1.需要在建連前就知道埠的話,需要 bind 2.需要透過指定的埠來通訊的話,需要 bind 具體到上面那兩個程式,本來用的是TCP,客戶端就不用繫結埠了,繫結之後只能執行一個client 的程式,是屬於自己程式中人為設定的障礙,而從伺服器那邊得到的客戶機連線埠號(是系統自動分配的)與這邊客戶機繫結的埠號根本是不相關的,所以客戶 繫結也就失去了意義。 注意: 一個埠可以用於多個連線(比如多個客戶端連線伺服器的同一埠)。但是在同一個作業系統上,即伺服器和客戶端都是本機上,多個客戶端去連線伺服器,只有第一個客戶端的連線會被接收,第二個客戶端的連線請求不會被接收。 首先,伺服器和客戶端都可以bind,bind並不是伺服器的專利。 客戶端程序bind埠: 由程序選擇一個埠去連伺服器,(如果預設情況下,呼叫bind函式時,核心指定的埠是同一個,那麼執行多個呼叫了bind 的client 程式,會出現埠被佔用的錯誤)注意這裡的埠是客戶端的埠。如果不分配就表示交給核心去選擇一個可用埠。 客戶端程序bind IP地址:相當於為傳送出去的IP資料報分配了源IP地址,但交給程序分配IP地址的時候(就是這樣寫明瞭bind IP地址的時候)這個IP地址必須是主機的一個介面,不能分配一個不存在的IP。如果不分配就表示由核心根據所用的輸出介面來選擇源IP地址。 一般情況下客戶端是不用呼叫bind函式的,一切都交給核心搞定! 服務端程序bind埠:基本是必須要做的事情,比如一個伺服器啟動時(比如freebsd),它會一個一個的捆綁眾所周知的埠來提供服務,同樣,如果bind了一個埠就表示我這個伺服器會在這個埠提供一些“特殊服務”。 服務端程序bind IP地址:目的是限制了服務端程序建立的socket只接受那些目的地為此IP地址的客戶連結,一般一個伺服器程式裡都有 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 只是針對IP4,IP6程式碼不太一樣 這樣一句話,意思就是:我不指定客戶端的IP,隨便連,來者不拒! 總之只要你bind時候沒有指定哪一項(置為0),核心會幫你選擇。
原因: 1、 因為伺服器是時時在監聽有沒有客戶端的連線,如果伺服器不繫結IP和埠的話,客戶端上線的時候怎麼連到伺服器呢,所以伺服器要繫結IP和埠,而客戶端就不需要了,客戶端上線是主動向伺服器發出請求的,因為伺服器已經綁定了IP和埠,所以客戶端上線的就向這個IP和埠發出請求,這時因為客戶開始發資料了(發上線請求),系統就給客戶端分配一個隨機埠,這個埠和客戶端的IP會隨著上線請求一起發給伺服器,服務收到上線請求後就可以從中獲起發此請求的客戶的IP和埠,接下來伺服器就可以利用獲起的IP和埠給客戶端迴應訊息了。 2、採用UDP通訊 1)若有客戶端和伺服器之分的程式,建立sock後即可在該socket上用recvfrom/sendto方法傳送接受資料了,因為客戶端只需要用sendto傳送資料到指定的地址,當然若是bind了,程式也沒什麼問題,區別就是系統用預設自動bind()指定你自己的socket引數地址(特別是在指定特定埠的UDP對等通訊)只是這種情況沒有這樣用的。 那UDP伺服器是怎麼知道客戶端的IP地址和UDP埠? 一般來說有兩種方式: 一種是客戶端發訊息顯式地告訴伺服器IP地址和埠,訊息內容就包括IP地址和UDP埠。 另外一種就是隱式的,伺服器從收到的包的頭部中得到包的源IP地址和埠。 2)若是沒有客戶端和伺服器之分的程式,即自己指定特定埠的UDP對等通訊,則客戶端和伺服器都需要bind()IP地址和埠了。 通常udp服務端根本不需要知道客戶端的socket,它直接建立一個socket用於傳送即可,udp通訊的關鍵只在於IP和埠。 多個客戶端如果需要點到點分發,必須給服務端socket迴圈設定每個客戶端的IP併發出,但更常用的是廣播分發,服務端socket設定一個X.X.X.255的廣播地址並始終向它傳送,每個客戶端建立的socket只需要繫結這個廣播地址便可以收到。 客戶端用不用bind 的區別 無連線的socket的客戶端和服務端以及面向連線socket的服務端透過呼叫bind函式來配置本地資訊。使用bind函式時,透過將my_addr.sin_port置為0,函式會自動為你選擇一個未佔用的埠來使用。 Bind()函式在成功被呼叫時返回0;出現錯誤時返回"-1"並將errno置為相應的錯誤號。需要注意的是,在呼叫bind函式時一般不要將埠號置為小於1024的值,因為1到1024是保留埠號,你可以選擇大於1024中的任何一個沒有被佔用的埠號。 有連線的socket客戶端透過呼叫Connect函式在socket資料結構中儲存本地和遠端資訊,無須呼叫bind(),因為這種情況下只需知道目的機器的IP地址,而客戶透過哪個埠與伺服器建立連線並不需要關心,socket執行體為你的程式自動選擇一個未被佔用的埠,並通知你的程式資料什麼時候開啟埠。(當然也有特殊情況,linux系統中rlogin命令應當呼叫bind函式繫結一個未用的保留埠號,還有當客戶端需要用指定的網路裝置介面和埠號進行通訊等等) 總之: 1.需要在建連前就知道埠的話,需要 bind 2.需要透過指定的埠來通訊的話,需要 bind 具體到上面那兩個程式,本來用的是TCP,客戶端就不用繫結埠了,繫結之後只能執行一個client 的程式,是屬於自己程式中人為設定的障礙,而從伺服器那邊得到的客戶機連線埠號(是系統自動分配的)與這邊客戶機繫結的埠號根本是不相關的,所以客戶 繫結也就失去了意義。 注意: 一個埠可以用於多個連線(比如多個客戶端連線伺服器的同一埠)。但是在同一個作業系統上,即伺服器和客戶端都是本機上,多個客戶端去連線伺服器,只有第一個客戶端的連線會被接收,第二個客戶端的連線請求不會被接收。 首先,伺服器和客戶端都可以bind,bind並不是伺服器的專利。 客戶端程序bind埠: 由程序選擇一個埠去連伺服器,(如果預設情況下,呼叫bind函式時,核心指定的埠是同一個,那麼執行多個呼叫了bind 的client 程式,會出現埠被佔用的錯誤)注意這裡的埠是客戶端的埠。如果不分配就表示交給核心去選擇一個可用埠。 客戶端程序bind IP地址:相當於為傳送出去的IP資料報分配了源IP地址,但交給程序分配IP地址的時候(就是這樣寫明瞭bind IP地址的時候)這個IP地址必須是主機的一個介面,不能分配一個不存在的IP。如果不分配就表示由核心根據所用的輸出介面來選擇源IP地址。 一般情況下客戶端是不用呼叫bind函式的,一切都交給核心搞定! 服務端程序bind埠:基本是必須要做的事情,比如一個伺服器啟動時(比如freebsd),它會一個一個的捆綁眾所周知的埠來提供服務,同樣,如果bind了一個埠就表示我這個伺服器會在這個埠提供一些“特殊服務”。 服務端程序bind IP地址:目的是限制了服務端程序建立的socket只接受那些目的地為此IP地址的客戶連結,一般一個伺服器程式裡都有 servaddr.sin_addr.s_addr = htonl(INADDR_ANY); // 只是針對IP4,IP6程式碼不太一樣 這樣一句話,意思就是:我不指定客戶端的IP,隨便連,來者不拒! 總之只要你bind時候沒有指定哪一項(置為0),核心會幫你選擇。