INADDR_ANY就是inet_addr("0.0.0.0")服務器
首先,須要明確的是當服務器的監聽地址是INADDR_ANY時設置的是服務器的IP地址。網絡
其次,當服務器的監聽地址是INADDR_ANY時含義是讓服務器端計算機上的全部網卡的IP地址均可以做爲服務器IP地址,也即監聽外部客戶端程序發送到服務器端全部網卡的網絡請求。socket
好比,個人網絡爲:192.168.1.102. 因而就有下面的程序:函數
服務端:spa
#include <stdio.h> #include <winsock2.h> // winsock接口 #pragma comment(lib, "ws2_32.lib") // winsock實現 int main() { WORD wVersionRequested; // 雙字節,winsock庫的版本 WSADATA wsaData; // winsock庫版本的相關信息 wVersionRequested = MAKEWORD(1, 1); // 0x0101 即:257 // 加載winsock庫並肯定winsock版本,系統會把數據填入wsaData中 WSAStartup( wVersionRequested, &wsaData ); // AF_INET 表示採用TCP/IP協議族 // SOCK_STREAM 表示採用TCP協議 // 0是一般的默認狀況 unsigned int sockSrv = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_family = AF_INET; // TCP/IP協議族 addrSrv.sin_addr.S_un.S_addr = INADDR_ANY; //inet_addr("0.0.0.0"); addrSrv.sin_port = htons(8888); // socket對應的端口 // 將socket綁定到某個IP和端口(IP標識主機,端口標識通訊進程) bind(sockSrv,(SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); // 將socket設置爲監聽模式,5表示等待鏈接隊列的最大長度 listen(sockSrv, 5); SOCKADDR_IN addrClient; int len = sizeof(SOCKADDR); while(1) { // sockSrv爲監聽狀態下的socket // &addrClient是緩衝區地址,保存了客戶端的IP和端口等信息 // len是包含地址信息的長度 // 若是客戶端沒有啓動,那麼程序一直停留在該函數處 unsigned int sockConn = accept(sockSrv,(SOCKADDR*)&addrClient, &len); char sendBuf[100] = {0}; sprintf(sendBuf,"%s", inet_ntoa(addrClient.sin_addr)); // 將客戶端的IP地址保存下來 send(sockConn, sendBuf, strlen(sendBuf) + 1, 0); // 發送數據到客戶端,最後一個參數通常設置爲0 char recvBuf[100] = {0}; recv(sockConn, recvBuf, 100, 0); // 接收客戶端數據,最後一個參數通常設置爲0 printf("%s\n", recvBuf); closesocket(sockConn); } closesocket(sockSrv); WSACleanup(); return 0; }
客戶端:code
#include <winsock2.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(1, 1); WSAStartup( wVersionRequested, &wsaData ); SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("192.168.1.102"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8888); int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char recvBuf[100] = {0}; recv(sockClient, recvBuf, 100, 0); printf("%s\n", recvBuf); send(sockClient, "hello world", strlen("hello world") + 1, 0); closesocket(sockClient); WSACleanup(); return 0; }
固然客戶端也能夠用回測地址(設服務端與客戶端在同一臺機子上):blog
#include <winsock2.h> #include <stdio.h> #pragma comment(lib, "ws2_32.lib") int main() { WORD wVersionRequested; WSADATA wsaData; wVersionRequested = MAKEWORD(1, 1); WSAStartup( wVersionRequested, &wsaData ); SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); SOCKADDR_IN addrSrv; addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); addrSrv.sin_family = AF_INET; addrSrv.sin_port = htons(8888); int ret = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR)); char recvBuf[100] = {0}; recv(sockClient, recvBuf, 100, 0); printf("%s\n", recvBuf); send(sockClient, "hello world", strlen("hello world") + 1, 0); closesocket(sockClient); WSACleanup(); return 0; }
固然啦,若是服務端用192.168.1.102做爲監聽IP,客戶端用192.168.1.102去connect, 那也是能夠的。接口
問:隊列
不少書上都說「將sin_addr設置爲INADDR_ANY,則表示全部的IP地址,也即全部的計算機」,這樣的解說讓人費解。進程
答:
INADDR_ANY轉換過來就是0.0.0.0,泛指本機的意思,也就是表示本機的全部IP,由於有些機子不止一塊網卡,多網卡的狀況下,這個就表示全部網卡ip地址的意思。
當服務器的監聽地址是INADDR_ANY時,意思不是監聽全部的客戶端IP。而是服務器端的IP地址能夠隨意配置,這樣使得該服務器端程序能夠運行在任意計算機上,可以使任意計算機做爲服務器,便於程序移植。將INADDR_ANY換成127.0.0.1也能夠達到一樣的目的。這樣,看成爲服務器的計算機的IP有變更或者網卡數量有增減,服務器端程序都可以正常監聽來自客戶端的請求。我是這麼理解的。
好比一臺電腦有3塊網卡,分別鏈接三個網絡,那麼這臺電腦就有3個ip地址了,若是某個應用程序須要監聽某個端口,那他要監聽哪一個網卡地址的端口呢?若是綁定某個具體的ip地址,你只能監聽你所設置的ip地址所在的網卡的端口,其它兩塊網卡沒法監聽端口,若是我須要三個網卡都監聽,那就須要綁定3個ip,也就等於須要管理3個套接字進行數據交換,這樣豈不是很繁瑣?因此出現INADDR_ANY,你只需綁定INADDR_ANY,管理一個套接字就行,無論數據是從哪一個網卡過來的,只要是綁定的端口號過來的數據,均可以接收到。