成人AV在线无码|婷婷五月激情色,|伊人加勒比二三四区|国产一区激情都市|亚洲AV无码电影|日av韩av无码|天堂在线亚洲Av|无码一区二区影院|成人无码毛片AV|超碰在线看中文字幕

VS2010 C 學(xué)習(xí)(4):WinSock域名查詢(xún)解析程序

VS2010 C 學(xué)習(xí)(4):WinSock 域名查詢(xún)解析學(xué)習(xí)VC 編制的Socket 域名查詢(xún)、解析程序,主要練習(xí)網(wǎng)絡(luò)Winsock 的應(yīng)用。一、 主要內(nèi)容:1. 根據(jù)IP 地址查詢(xún)主機(jī)信息;

VS2010 C 學(xué)習(xí)(4):WinSock 域名查詢(xún)解析

學(xué)習(xí)VC 編制的Socket 域名查詢(xún)、解析程序,主要練習(xí)網(wǎng)絡(luò)Winsock 的應(yīng)用。

一、 主要內(nèi)容:

1. 根據(jù)IP 地址查詢(xún)主機(jī)信息;

2. 根據(jù)網(wǎng)址查詢(xún)主機(jī)信息、DNS 解析地址;

,

二、 設(shè)計(jì)實(shí)現(xiàn):

1. 根據(jù)IP 地址查詢(xún)主機(jī)信息;

根據(jù)IP 地址調(diào)用gethostbyaddr 函數(shù) ,分析hostent 結(jié)構(gòu)體 獲取主機(jī)信息。

2. 根據(jù)網(wǎng)址查詢(xún)主機(jī)信息、DNS 解析地址;

根據(jù)網(wǎng)址 調(diào)用getaddinfo 函數(shù)查詢(xún)DNS 服務(wù)器 ,查詢(xún)鏈表依次獲取該網(wǎng)址的主機(jī)信息,分析SOCKADDR_IN結(jié)構(gòu)體,解析出IP 地址。

三、 基礎(chǔ)知識(shí):

(一) 域名解析DNSR(domain name system resolution)

1. 域名解析

域名解析是把域名指向網(wǎng)站空間IP ,讓人們通過(guò)注冊(cè)的域名可以方便地訪問(wèn)到網(wǎng)站一種服務(wù)。域名解析也叫域名指向、服務(wù)器設(shè)置、域名配置以及反向IP 登記等等。說(shuō)得簡(jiǎn)單點(diǎn)就是將好記的域名解析成IP ,服務(wù)由DNS 服務(wù)器完成,是把域名解析到一個(gè)IP 地址,然后在此IP 地址的主機(jī)上將一個(gè)子目錄與域名綁定。

IP 地址是網(wǎng)路上標(biāo)識(shí)您站點(diǎn)的數(shù)字地址,為了方便記憶,采用域名來(lái)代替IP 地址標(biāo)識(shí)站點(diǎn)地址。域名解析就是域名到IP 地址的轉(zhuǎn)換過(guò)程。域名的解析工作由DNS 服務(wù)器完成。

我們知道域名是為了方便記憶而專(zhuān)門(mén)建立的一套地址轉(zhuǎn)換系統(tǒng),要訪問(wèn)一臺(tái)互聯(lián)網(wǎng)上的服務(wù)器,最終還必須通過(guò)IP 地址來(lái)實(shí)現(xiàn),域名解析就是將域名重新轉(zhuǎn)換為IP 地址的過(guò)程。一個(gè)域名對(duì)應(yīng)一個(gè)IP 地址,一個(gè)IP 地址可以對(duì)應(yīng)多個(gè)域名;所以多個(gè)域名可以同時(shí)被解析到一個(gè)IP 地址。域名解析需要由專(zhuān)門(mén)的域名解析服務(wù)器(DNS ) 來(lái)完成。

解析過(guò)程,比如,一個(gè)域名為:***.com,是想看到這個(gè)現(xiàn)HTTP 服務(wù),如果要訪問(wèn)網(wǎng)站,就要進(jìn)行解析,首先在域名注冊(cè)商那里通過(guò)專(zhuān)門(mén)的DNS 服務(wù)器解析到一個(gè)WEB 服務(wù)器的一個(gè)固定IP 上:211.214.1.***,然后,通過(guò)WEB 服務(wù)器來(lái)接收這個(gè)域名,把***.com這個(gè)域名映射到這臺(tái)服務(wù)器上。那么,輸入***.com這個(gè)域名就可以實(shí)現(xiàn)訪問(wèn)網(wǎng)站內(nèi)容了. 即實(shí)現(xiàn)了域名解析的全過(guò)程;

人們習(xí)慣記憶域名,但機(jī)器間互相只認(rèn)IP 地址,域名與IP 地址之間是對(duì)應(yīng)的,它們之間的轉(zhuǎn)換工作稱(chēng)為域名解析,域名解析需要由專(zhuān)門(mén)的域名解析服務(wù)器來(lái)完成,整個(gè)過(guò)程是自動(dòng)進(jìn)行的。

,

域名解析協(xié)議(DNS )用來(lái)把便于人們記憶的主機(jī)域名和電子郵件地址映射為計(jì)算機(jī)易于識(shí)別的IP 地址。DNS 是一種c/s的結(jié)構(gòu),客戶(hù)機(jī)就是用戶(hù)用于查找一個(gè)名字對(duì)應(yīng)的地址,而服務(wù)器通常用于為別人提供查詢(xún)服務(wù)。

2. TTL 值

全稱(chēng)是“生存時(shí)間(Time To Live)”,簡(jiǎn)單的說(shuō)它表示DNS 記錄在DNS 服務(wù)器上緩存時(shí)間。

3. A 記錄

WEB 服務(wù)器的IP 指向A (Address) 記錄是用來(lái)指定主機(jī)名(或域名)對(duì)應(yīng)的IP 地址記錄。

(二) Socket

1. socket 定義

socket 接口是TCP/IP網(wǎng)絡(luò)的API ,socket 接口定義了許多函數(shù)或例程,程序員可以用它們來(lái)開(kāi)發(fā)TCP/IP網(wǎng)絡(luò)上的應(yīng)用程序。

每一個(gè)socket 都用一個(gè)半相關(guān)描述{協(xié)議、本地地址、本地端口}來(lái)表示;一個(gè)完整的套接字則用一個(gè)相關(guān)描述{協(xié)議、本地地址、本地端口、遠(yuǎn) 程地址、遠(yuǎn)程端口}來(lái)表示。

socket 也有一個(gè)類(lèi)似于打開(kāi)文件的函數(shù)調(diào)用,該函數(shù)返回一個(gè)整型的socket 描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫?是通過(guò)socket 來(lái)實(shí)現(xiàn)的。

2. Socket 類(lèi)型

● 流式socket (SOCK_STREAM)

流式套接字提供可靠的、面向連接的通信流;它使用TCP 協(xié)議,從而保證了數(shù)據(jù)傳輸?shù)恼_性和順序性。

● 數(shù)據(jù)報(bào)socket (SOCK_DGRAM)

數(shù)據(jù)報(bào)套接字定義了一種無(wú)連接的服務(wù),數(shù)據(jù)通過(guò)相互獨(dú)立的報(bào)文進(jìn)行傳輸,是無(wú)序的,并且不保證是可靠、無(wú)差錯(cuò)的。它使用數(shù)據(jù)報(bào)協(xié)議UDP 。

● 原始socket

原始套接字允許對(duì)底層協(xié)議如IP 或ICMP 進(jìn)行直接訪問(wèn),它功能強(qiáng)大但使用較為不

,

便,主要用于一些協(xié)議的開(kāi)發(fā)。

3. 地址數(shù)據(jù)結(jié)構(gòu)

● 使用C/C 開(kāi)發(fā)socket 程序時(shí),使用sockaddr 和sockaddr_in這兩個(gè)結(jié)構(gòu)類(lèi)型來(lái)保存socket 信息。

● 這兩個(gè)數(shù)據(jù)類(lèi)型是等效的,可以相互轉(zhuǎn)化,通常sockaddr_in數(shù)據(jù)類(lèi)型使用更為方便。

struct sockaddr

{

unsigned short sa_family; /*協(xié)議族*/

char sa_data[14]; /*14字節(jié)的 協(xié)議地址,包含該socket 的IP 地址和端口號(hào)。*/ };

struct sockaddr_in

{

short int sa_family; /*協(xié)議族*/

unsigned short int sin_port; /*端口號(hào)*/

struct in_addr sin_addr; /*IP地址*/

unsigned char sin_zero[8]; /*填充0 以保持與struct sockaddr同樣大小*/ };

4. 協(xié)議族

● 上述結(jié)構(gòu)中的sa_family字段用于描述socket 中的協(xié)議族,其定義于netinet/in.h

5. 數(shù)據(jù)存儲(chǔ)優(yōu)先順序

● 計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先(稱(chēng)為大端模式)和低位字節(jié)優(yōu)先(稱(chēng)為小端模式,PC 機(jī)通常采用)。

,

● Internet 上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,因此在有些情況下,需要對(duì)這兩個(gè)字節(jié)存儲(chǔ)優(yōu)先順序進(jìn)行相互轉(zhuǎn)化。

● 對(duì)字節(jié)存儲(chǔ)優(yōu)先順序轉(zhuǎn)化可能用到4個(gè)函數(shù):htons()、 ntohs()、htonl()和ntohl()。這4個(gè)函數(shù)分別實(shí)現(xiàn)網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序的轉(zhuǎn)化,其中h 表示host ,n 表示network ,s 表示short ,l 表示long 。通常16位的IP 端口號(hào)用s ,而IP 地址用l 。 ● 調(diào)用該函數(shù)只是使其得到相應(yīng)的字節(jié)序, 用戶(hù)不需清楚該系統(tǒng)的主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序是否真正相等。如果是相同不需要轉(zhuǎn)換的話(huà),該系統(tǒng)的這些函數(shù)會(huì)定義成空宏。

6. 字節(jié)優(yōu)先順序轉(zhuǎn)換函數(shù)

7. 地址格式轉(zhuǎn)化

● 通常用戶(hù)在表達(dá)地址時(shí)采用的是點(diǎn)分十進(jìn)制表示的數(shù)值(或者是以冒號(hào)分開(kāi)的十進(jìn)制IPv6地址),而在通常使用的socket 編程中所使用的則是 二進(jìn)制值,這就需要將這兩個(gè)數(shù)值進(jìn)行轉(zhuǎn)換。

● 在IPv4中用到的函數(shù)有inet_aton()、inet_addr()和inet_ntoa(),而 IPv4和IPv6兼容的函數(shù)有inet_pton()和inet_ntop()。由于IPv6是下一代互聯(lián)網(wǎng)的標(biāo)準(zhǔn)協(xié)議,后面涉及的函數(shù)都能夠同時(shí)兼容IPv4和IPv6,但在具體舉例時(shí)仍以IPv4為例。

● 這里inet_pton()函數(shù)是將點(diǎn)分十進(jìn)制地址映射為二進(jìn)制地址,而inet_ntop()是

,

將二進(jìn)制地址映射為點(diǎn)分十進(jìn)制地址。

8. inet_pton函數(shù)

9. inet_ntop函數(shù)

10. 主機(jī)名

通常,人們?cè)谑褂眠^(guò)程中都不愿意記憶冗長(zhǎng)的IP 地址,尤其到IPv6時(shí),地址長(zhǎng)度多達(dá)128位。因此,使用主機(jī)名將會(huì)是很好的選擇。

,

● 在Linux 中,同樣有一些函數(shù)可以實(shí)現(xiàn)主機(jī)名和地址的轉(zhuǎn)化,最為常見(jiàn)的有g(shù)ethostbyname()、gethostbyaddr()和getaddrinfo()等,它們都可以實(shí)現(xiàn)IPv4和IPv6的地址和主機(jī)名之間的轉(zhuǎn)化。其中g(shù)ethostbyname()將主機(jī)名轉(zhuǎn)化為IP 地址,gethostbyaddr()則是逆操作,將IP 地址轉(zhuǎn)化為主機(jī)名,另外getaddrinfo()還能實(shí)現(xiàn)自動(dòng)識(shí)別IPv4地址和IPv6地址。

● gethostbyname()和gethostbyaddr()都涉及一個(gè)hostent 的結(jié)構(gòu)體。

11. hostent 結(jié)構(gòu)體

struct hostent

{

char *h_name; /*正式主機(jī)名*/

char **h_aliases; /*主機(jī)別名*/

int h_addrtype; /*地址類(lèi)型*/

int h_length; /*地址字節(jié)長(zhǎng)度*/

char **h_addr_list; /*指向IPv4或IPv6的地址指 針數(shù)組*/

};

● 調(diào)用gethostbyname()函數(shù)或gethostbyaddr()函數(shù)后就能返回hostent 結(jié)構(gòu)體的相關(guān)信息。

12. gethostbyname 函數(shù)

? 調(diào)用該函數(shù)時(shí)可以首先對(duì)hostent 結(jié)構(gòu)體中的h_addrtype和h_length進(jìn)行設(shè)置,若為IPv4可設(shè)置為AF_INET和4;若為IPv6可設(shè)置為AF_INET6和16;若不設(shè)置則默認(rèn)為IPv4地址類(lèi)型。

13. getaddrinfo 函數(shù)

,

14. addrinfo 結(jié)構(gòu)體

getaddrinfo()函數(shù)涉及一個(gè)addrinfo 的結(jié)構(gòu)體:

struct addrinfo

{

int ai_flags;

/*AI_PASSIVE, AI_CANONNAME;*/ int ai_family; /*地址族*/

int ai_socktype; /*socket類(lèi)型*/

int ai_protocol; /*協(xié)議類(lèi)型*/

size_t ai_addrlen; /*地址字節(jié)長(zhǎng)度*/

char *ai_canonname; /*主機(jī)名*/

struct sockaddr *ai_addr; /*socket結(jié)構(gòu)體*/

struct addrinfo *ai_next; /*下一個(gè)指針鏈表*/

};

15. addrinfo 常見(jiàn)選項(xiàng)值

,

? 通常服務(wù)器端在調(diào)用getaddrinfo()之前,ai_flags設(shè)置AI_PASSIVE,用于 bind()函數(shù)(用于端口和地址的綁定,后面會(huì)講到),主機(jī)名nodename 通常會(huì)設(shè)置為NULL 。

? 客戶(hù)端調(diào)用getaddrinfo()時(shí),ai_flags一般不設(shè)置AI_PASSIVE,但是主機(jī)名 nodename 和服務(wù)名servname (端口)則應(yīng)該不為空。

? 即使不設(shè)置ai_flags為AI_PASSIVE,取出的地址也可以被綁定,很多程序中ai_flags直接設(shè)置為0,即3個(gè)標(biāo)志位都不設(shè)置,這種情況 下只要hostname 和servname 設(shè)置的沒(méi)有問(wèn)題就可以正確綁定。

/*#include files… */

int main()

{

struct addrinfo hints, *res = NULL;

int rc;

memset(&hints, 0, sizeof(hints));

/*設(shè)置addrinfo 結(jié)構(gòu)體中各參數(shù) */

hints.ai_flags = AI_CANONNAME;

hints.ai_family = AF_UNSPEC;

hints.ai_socktype = SOCK_DGRAM;

hints.ai_protocol = IPPROTO_UDP;

,

/*調(diào)用getaddinfo 函數(shù)*/

rc = getaddrinfo("localhost", NULL, &hints, &res);

if (rc != 0)

{

perror("getaddrinfo");

exit(1);

}

else

{

printf("Host name is sn", res->ai_canonname);

}

exit(0);

}

(三) 編程注意

● WS2_32.lib是網(wǎng)絡(luò)套接字的庫(kù)。兩種方法加入

1、 菜單的 項(xiàng)目 - 屬性 - Linker - Input - Additional Dependencies 加上

2、 直接在代碼里面 #pragma comment(lib, "ws2_32.lib")

● WSAStartup

使用Winsock 庫(kù)函數(shù)之前, 必須先調(diào)用函數(shù)WSAStartup, 該函數(shù)負(fù)責(zé)初始化動(dòng)態(tài)連接庫(kù)Ws2_32.dll.

函數(shù)定義:

int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );

● wVersionRequested

標(biāo)簽: