做爲一名初學者,和你們同樣,對網絡這個東西敬之迷之卻又惑之。對我而言,最爽的就是弄懂那些本身不知道的東西了。那麼,咱麼就一塊兒學習socket編程吧!linux
首先,設備想要在互聯網的大海里遨遊就必須的有一個本身在這個圈子裏惟一的標識,這就是ip地址,通常來講,ip地址具備惟一性,就像在學校裏你的學號是獨一無二的同樣。ip地址包括網絡號和主機號兩個部分,好比百度的ip:123.125.115.110,前三段(123.125.115)便是它的網絡號,最後一段(110)就是它的主機號。因爲ip地址這一堆堆的數字總是讓人記不住,因此機智的人類發明了域名。域名和ip能夠是一一對應,也能夠是一個域名對應多個ip(好比百度就有兩個ip,可是隻有一個baidu.com域名)。ip地址就是主機地址。ios
說白了,ip就是一串數字,目前爲止是32bit的無符號數。編程
在數據傳輸的過程當中,一定存在兩端,一端發送數據,一端接收數據,所以出現了客戶端和服務器,但不是說客戶端就必定只能接收數據,服務器就只能發送數據,在通訊時,每每兩端都有在發送和接受數據。這裏要特別注意一點:客戶端和服務器並不單純的只是兩臺設備,他們是兩個進程。換句話說,一臺設備上可能跑多個客戶端或者多個服務器。網絡就是依靠兩端的某些信息而創建的,包含這些信息的結構叫作套接字對,而這些信息自己就是套接字。套接字包含了主機地址和端口號。處於客戶端的套接字成爲客戶端套接字,處於服務器端的套接字稱爲服務器套接字。當兩臺設備想要鏈接起來以便通訊時,咱們能夠調用 套接字接口 來讓他們完成「交易」結合成對,當「交易」完成時,他們就能夠愉快的相互「說話」了。windows
套接字接口分爲客戶端套接字接口和服務器端套接字接口。服務器
客戶端套接字接口:getaddrinfo()、socket()、connect()、rio_writen()、rio_readlineb()、close()網絡
服務器端套接字接口:getaddrinfo()、socket()、bind()、listen()、accept()、rio_readlineb()、rio_writen()、close()dom
固然,套接字接口還不止這些,這些只是完成客戶端與服務器相互連通並進行簡單的數據傳輸所用到的套接字接口。socket
瞭解到這,咱們能夠來作一個小實驗,來看看百度域名到底映射了多少ip。tcp
第一步:咱們得進行socket版本協商,初始化socket;函數
第二步:填充addrinfo結構體(結構體的具體細節百度吧,這裏就不貼了)
第三步:根據域名獲取映射ip存於addrinfo鏈表中
第四步:獲取域名的數字地址字符串
第五步:爲了養成良好的編程習慣,切不要忘告終束時應該釋放內存
搞定!哦,對了,差點忘了貼代碼了...
1 #include <iostream> 2 #include <ws2tcpip.h> 3 #pragma comment(lib,"ws2_32.lib") 4 5 int main(int argc, char* argv[]) 6 { 7 const int MAXLINE = 2048; 8 struct addrinfo *p, *listp, hints; 9 char buf[MAXLINE]; 10 int rc, flags; 11 12 //第一步:進行socket版本協商並初始化socket(使用socket函數以前的必要步驟) 13 WORD wVersionRequested; 14 WSADATA wsaData; 15 int err; 16 17 wVersionRequested = MAKEWORD(1, 1); 18 19 err = WSAStartup(wVersionRequested, &wsaData); 20 if (err != 0) { 21 /* Tell the user that we could not find a usable */ 22 /* WinSock DLL. */ 23 return 0; 24 } 25 26 /* Confirm that the WinSock DLL supports 1.1.*/ 27 /* Note that if the DLL supports versions greater */ 28 /* than 1.1 in addition to 1.1, it will still return */ 29 /* 1.1 in wVersion since that is the version we */ 30 /* requested. */ 31 32 if (LOBYTE(wsaData.wVersion) != 1 || 33 HIBYTE(wsaData.wVersion) != 1) { 34 /* Tell the user that we could not find a usable */ 35 /* WinSock DLL. */ 36 int vl = LOBYTE(wsaData.wVersion); 37 int vh = HIBYTE(wsaData.wVersion); 38 return 0; 39 } 40 41 /* The WinSock DLL is acceptable. Proceed. */ 42 43 /*if (argc != 2) 44 { 45 fprintf(stderr, "usage:%s <domain name>\n", argv[0]); 46 exit(0); 47 }*/ 48 49 //end 50 51 char name[50]; 52 std::cin >> name; 53 54 //第二步:填充addrinfo結構體 55 memset(&hints, 0, sizeof(struct addrinfo)); 56 hints.ai_family = AF_INET; 57 hints.ai_socktype = SOCK_STREAM; 58 //end 59 60 //第三步:根據域名name獲取映射ip存於listp中 61 if ((rc = getaddrinfo(name, NULL, &hints, &listp)) != 0) 62 { 63 std::cout << "getaddrinfo error:" << gai_strerror(rc) << std::endl; 64 WSACleanup(); 65 return 0; 66 } 67 //end 68 69 //第四步:獲取域名的數字地址字符串 70 flags = NI_NUMERICHOST; 71 for (p = listp; p; p = p->ai_next) 72 { 73 getnameinfo(p->ai_addr, p->ai_addrlen, buf, MAXLINE, NULL, 0, flags); 74 std::cout << buf << std::endl; 75 } 76 //end 77 78 //第五步:釋放listp(因爲較小因此能夠忽略,只是爲了養成良好的編程習慣最好加上) 79 freeaddrinfo(listp); 80 //end 81 system("pause"); 82 WSACleanup(); 83 return 0; 84 }
說明:本代碼基於vs2015調試運行成功。因爲DEV C++中不認識#pragma,所以在DEV C++中不能運行。還請注意,windows下,套接字接口包含於頭文件<ws2tcpip.h>中,同時還應將其配套的庫「ws2_32.lib」一塊兒包含在程序裏,否則會出現這個狀況:
//error LNK2019: 沒法解析的外部符號 __imp__WSAStartup@8,該符號在函數 _main 中被引用
在linux下,頭文件爲<netdb.h>。
入門篇結束~待續...