1. 程式人生 > >socket繫結的ip為INADDR_ANY 的意義

socket繫結的ip為INADDR_ANY 的意義

socket INADDR_ANY 監聽0.0.0.0地址 socket只繫結埠讓路由表決定傳到哪個ip

其中INADDR_ANY就是指定地址為0.0.0.0的地址,這個地址事實上表示不確定地址,或“所有地址”、“任意地址”。
如果指定ip地址為通配地址(INADDR_ANY),那麼核心將等到套接字已連線(TCP)或已在套接字上發出資料報時才選擇一個本地IP地址。
一般情況下,如果你要建立網路伺服器,則你要通知伺服器作業系統:請在某地址 xxx.xxx.xxx.xxx上的某埠 yyyy上進行偵聽,並且把偵聽到的資料包傳送給我。這個過程,你是通過bind()系統呼叫完成的。——也就是說,你的程式要繫結伺服器的某地址,或者說:把伺服器的某地址上的某端口占為已用。伺服器作業系統可以給你這個指定的地址,也可以不給你。

如果你的伺服器有多個網絡卡,
而你的服務(不管是在udp埠上偵聽,還是在tcp埠上偵聽),出於某種原因:可能是你的伺服器作業系統可能隨時增減IP地址,也有可能是為了省去確定伺服器上有什麼網路埠(網絡卡)的麻煩 —— 可以要在呼叫bind()的時候,告訴作業系統:“我需要在 yyyy 埠上偵聽,所以傳送到伺服器的這個埠,不管是哪個網絡卡/哪個IP地址接收到的資料,都是我處理的。”這時候,伺服器則在0.0.0.0這個地址上進行偵聽。

具體一點:

比如你的機器有三個ip   
  192.168.1.1   
  202.202.202.202   
  61.1.2.3    
  如果你serv.sin_addr.s_addr=inet_addr("192.168.1.1");      
  然後監聽100埠   
  這時其他機器只有connect   192.168.1.1:100才能成功。   
  connect   202.202.202.202:100和connect   61.1.2.3:100都會失敗。    
  如果serv.sin_addr.s_addr=htonl(INADDR_ANY);   的話,無論連線哪個ip都可以連上的,只要是往這個埠傳送的所有ip都能連上。

    對於客戶端如果繫結INADDR_ANY,情況類似。對於TCP而言,在connect()系統呼叫時將其綁頂到一具體的IP地址。選擇的依據是該地址所在子網到目標地址是可達的(reachable). 這時通過getsockname()系統呼叫就能得知具體使用哪一個地址。對於UDP而言, 情況比較特殊。即使使用connect()系統呼叫也不會繫結到一具體地址。這是因為對UDP使用connect()並不會真正向目標地址傳送任何建立連線的資料,也不會驗證到目標地址的可達性。它只是將目標地址的資訊記錄在內部的socket資料結構之中,共以後使用。只有當呼叫sendto()/send()時,由系統核心根據路由表決定由哪一個地址(網絡卡)傳送UDP packet.


P.S.

-----------------------------------------------------------------------------

在IP層中有一個路由表:
在MSDOS視窗可以執行命令:netstat -r 
來顯示路由表。根據路由表的條目從指定的網絡卡傳送資料。
ARP快取用:arp -a
來顯示。
通常乙太網幀的目的MAC地址,是下一跳的MAC地址。