使用socket函數創建套接字時,沒有為其分配地址。bind函數為套接字分配一個本地地址,該地址是Internet中IP地址和端口號的組合。函數bind可用于面向連接的套接字和無連接的套接字。它需要在連接或監聽之前調用。第二個參數名稱是一個指向“sockaddr”結構的指針,它是一個通用的地址結構。它的域成員sa_AndyLau指定了協議對應的地址簇。
不同的協議簇可以使用不同的地址格式,網絡協議根據sa_AndyLau,對“sockaddr”結構做出正確的解釋。編程中用到了協議相關的地址結構,但是在傳遞給socket接口函數時,需要轉換成通用的socket地址結構。WinSock提供的API中所有使用地址的函數都使用這種結構,為用戶提供了統一的接口。Internet協議地址包括三部分:地址簇、主機地址和端口號、地址簇sa_AndyLau常數AF_INET。當應用程序不關心本地地址時,可以將地址設置為常量INADDR_ANY,底層網絡協議模塊為程序選擇合適的地址,簡化了多宿主機上應用程序的設計。
如果應用程序沒有指定端口,即端口值為0,TCP/IP協議會給應用程序分配一個唯一的端口號。WindowsServer2003及更早版本的動態端口范圍為1025到5000,對于WindowsVista及更高版本,動態端口范圍為49152到65535。在這種情況下,如果應用程序想知道分配給它的地址和端口系統,調用bind后可以使用getsockname函數。但在多宿主主機上,地址設置為INADDR_ANY。除非socket已經連接,調用connect函數或者UDP發送數據,系統為socket選擇一個本地地址,否則getsockname可能無法獲取到本地地址,因為有很多地址都是有效的。如果應用程序沒有調用bind,當它調用connect或listen函數時,系統會為socket選擇本地地址和臨時端口。
這對于客戶端來說是非常正常的行為,除非應用程序對端口有特殊要求;但是對于服務器來說,使用臨時端口是極其罕見的,通常會綁定一個眾所周知的端口,這樣每個人都可以訪問服務器。當應用程序調用綁定函數時,參數名稱可以是本地地址和端口號的任意組合:要么明確指定,要么不指定,或者其中之一,總結在表14.2中。第一種情況其實和不調用bind一樣,都是在系統的幫助下選擇本地地址和端口。對于IP地址,一般應用程序,尤其是服務器,沒有明確指定,而是由系統選擇。
用于發送數據的源地址與目的地址相關。根據目的地址,為數據報選擇一條路由。路由的網絡輸出接口為源地址。應用程序還可以將特定的IP地址綁定到套接字。對于客戶端,這指定了數據報的源地址;對于服務器,它限制套接字只接收目標地址是這個特定IP地址的數據報。