Beej′s網(wǎng)絡(luò)編程指南_第1頁
Beej′s網(wǎng)絡(luò)編程指南_第2頁
Beej′s網(wǎng)絡(luò)編程指南_第3頁
Beej′s網(wǎng)絡(luò)編程指南_第4頁
Beej′s網(wǎng)絡(luò)編程指南_第5頁
已閱讀5頁,還剩40頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

1、Beejs 網(wǎng)絡(luò)編程指南,介紹,Hey! Socket 編程讓你沮喪嗎?從 man pages 中很難得到有用的信息嗎?你想 跟上時代去做一做 Internet 程序,但是為你在調(diào)用 connect() 前的 bind() 的結(jié)構(gòu)而愁眉不展?,讀者,這個文檔是寫成一個指南,而不是參考書。如果你剛開始 socket 編程并想找一本 入門書,那么你是我的讀者。這可不是一本完全的 socket 編程書。,平臺和編譯器,這篇文章中的大多數(shù)代碼都在一臺 Linux PC 上用 GNU 的 gcc 成功編譯過。 而且他們在一臺 HPUX 上用 gcc 也成功編譯過。但是注意,并不是每個代碼 片段都獨(dú)立測試

2、過。,目錄,什么是套接口? Internet 套接口的兩種類型 網(wǎng)絡(luò)理論 struct-要么了解他們,要么等異形入侵地球 Convert the Natives! IP 地址和如何處理他們,目錄,socket()-得到文件描述符! bind()-我們在哪個端口? connect()-Hello! listen()-有人給我打電話嗎? accept()-Thank you for calling port 3490.,目錄,send() 和 recv()-Talk to me, baby! sendto() 和 recvfrom()-Talk to me, DGRAM-style close()

3、 和 shutdown()-滾開! getpeername()-你是誰? gethostname()-我是誰?,目錄,DNS-你說“白宮”,我說 00 客戶-服務(wù)器背景知識 簡單的服務(wù)器 簡單的客戶端 數(shù)據(jù)報 Socket,目錄,阻塞 select()-多路同步 I/O,酷! 參考資料 Disclaimer and Call for Help,什么是 socket?,你始終聽到人們談?wù)撝?socket,而你不知道他的確切含義。那么,現(xiàn)在我告訴你: 他是使用 Unix 文件描述符 (fiel descriptor) 和其他程序通訊的方式。 什么? Ok-你也許聽到一些

4、Unix 高手 (hacker) 這樣說:“呀,Unix 中所有的東西 就是文件!”那個家伙也許正在說到一個事實(shí):Unix 程序在執(zhí)行任何形式的 I/O 的時候, 程序是在讀或者寫一個文件描述符。一個文件描述符只是一個和打開的文件相關(guān)聯(lián)的整數(shù)。 但是(注意后面的話),這個文件可能是一個網(wǎng)絡(luò)連接,F(xiàn)IFO,管道,終端,磁盤上的文件 或者什么其他的東西。Unix 中所有的東西是文件!因此,你想和 Internet 上別 的程序通訊的時候,你將要通過文件描述符。最好相信剛才的話。 現(xiàn)在你腦海中或許冒出這樣的念頭:“那么我從哪里得到網(wǎng)絡(luò)通訊的文件描述符呢,聰明 人?”無論如何,我要回答這個問題:你利用

5、系統(tǒng)調(diào)用 socket()。他返回套接口描 述符 (socket descriptor),然后你再通過他來調(diào)用 send() 和 recv()。 “但是.”,你可能現(xiàn)在叫起來,“如果他是個文件描述符,那么為什么不用一般的調(diào)用 read() 和 write() 來通過套接口通訊?”簡單的答案是:“你可以使用 一般的函數(shù)!”。詳細(xì)的答案是:“你可以,但是使用 send() 和 recv() 讓你更好的控制數(shù)據(jù)傳輸?!?有這樣一個事實(shí):在我們的世界上,有很多種套接口。有 DARPA Internet 地址 (Internet 套接口),本地節(jié)點(diǎn)的路徑名 (Unix 套接口),CCITT X.25 地

6、址 (你可以完全忽略 X.25 套接口)。 也許在你的 Unix 機(jī)器上還有其他的。我們在這里只講第一種:Internet 套接口。,Internet 套接口的兩種類型,什么意思?有兩種 Internet 套接口?是的。不,我在撒謊。其實(shí)還有很多,但是我可不想 嚇著你。我們這里只講兩種。 Except for this sentence, where Im going to tell you that Raw Sockets are also very powerful and you should look them up. 好了,好了。那兩種類型是什么呢?一種是 Stream Socket

7、s,另外一種是 Datagram Sockets。我們以后談到他們的時候也會用到 SOCK_STREAM 和 SOCK_DGRAM。 數(shù)據(jù)報套接口有時也叫“無連接套接口”(如果你確實(shí)要連接的時候用 connect()。) 流式套接口是可靠的雙向通訊的數(shù)據(jù)流。如果你向套接口安順序輸出“1,2”,那么他們 將安順序“1,2”到達(dá)另一邊。他們也是無錯誤的傳遞的,有自己的錯誤控制。 那么數(shù)據(jù)報套接口呢?為什么他叫無連接呢?為什么他是不可靠的呢?恩,有這樣的事實(shí): 如果你發(fā)送一個數(shù)據(jù)報,他可能到達(dá),他可能次序顛倒了。如果他到達(dá),那么在這個包的內(nèi)部 是無錯誤的。,網(wǎng)絡(luò)理論,既然我剛才提到了協(xié)議層,那么現(xiàn)在

8、是討論網(wǎng)絡(luò)究竟如何工作和演示 SOCK_DGRAM 的工作。當(dāng)然,你也可以跳過這一段,如果你認(rèn)為 已經(jīng)熟悉的話。 朋友們,現(xiàn)在是學(xué)習(xí) 數(shù)據(jù)封裝 (Data Encapsulation) 的時候了! 這非常非常重要。Its so important that you might just learn about it if you take the networks course here at Chico State ;-). 主要的內(nèi)容是:一個包,先是被第一個協(xié)議(在這里是 TFTP )包裝(“封裝”), 然后,整個數(shù)據(jù)(包括 TFTP 頭)被另外一個協(xié)議(在這里是 UDP )封裝,然后下

9、一個( IP ),一直重復(fù)下去,直到硬件(物理)層( Ethernet )。 當(dāng)另外一臺機(jī)器接收到包,硬件先剝?nèi)?Ethernet 頭,內(nèi)核剝?nèi)?IP 和 UDP 頭,TFTP 程序再剝?nèi)?TFTP 頭,最后得到數(shù)據(jù)。 現(xiàn)在我們終于講到臭名遠(yuǎn)播的 網(wǎng)絡(luò)分層模型 (Layered Network Model)。 這種網(wǎng)絡(luò)模型在描述網(wǎng)絡(luò)系統(tǒng)上相對其他模型有很多優(yōu)點(diǎn)。例如,你可以寫一個套接口 程序而不用關(guān)心數(shù)據(jù)的物理傳輸(串行口,以太網(wǎng),連接單元接口 (AUI) 還是其他介質(zhì)。 因為底層的程序為你處理他們。實(shí)際的網(wǎng)絡(luò)硬件和拓?fù)鋵τ诔绦騿T來說是透明的。,structs,注意這樣的事實(shí): 有兩種字節(jié)排列

10、順序:重要的字節(jié)在前面(有時叫 “octet”),或者不重要的字節(jié)在前面。 前一種叫“網(wǎng)絡(luò)字節(jié)順序 (Network Byte Order)”。有些機(jī)器在內(nèi)部是按照這個順序儲 存數(shù)據(jù),而另外一些則不然。當(dāng)我說某數(shù)據(jù)必須按照 NBO 順序,那么你要調(diào)用函數(shù)(例 如 htons() )來將他從本機(jī)字節(jié)順序 (Host Byte Order) 轉(zhuǎn)換過來。如果我 沒有提到 NBO, 那么就讓他是本機(jī)字節(jié)順序吧 第一個結(jié)構(gòu)(TM)-struct sockaddr. 這個數(shù)據(jù)結(jié)構(gòu) 為許多類型的套接口儲存套接口地址信息: struct sockaddr unsigned short sa_family; /

11、* address family, AF_xxx */ char sa_data14; /* 14 bytes of protocol address */ ;,sa_family 能夠是各種各樣的事情,但是在這篇文章中是 AF_INET。 sa_data 為套接口儲存目標(biāo)地址和端口信息??瓷先ズ鼙孔?,不是嗎。 為了對付 struct sockaddr,程序員創(chuàng)造了一個并列的結(jié)構(gòu): struct sockaddr_in (in 代表 Internet.) struct sockaddr_in short int sin_family; /* Address family */ unsigned

12、 short int sin_port; /* Port number */ struct in_addr sin_addr; /* Internet address */ unsigned char sin_zero8; /* Same size as struct sockaddr */ ;,這個數(shù)據(jù)結(jié)構(gòu)讓可以輕松處理套接口地址的基本元素。注意 sin_zero (他 被加入到這個結(jié)構(gòu),并且長度和 struct sockaddr 一樣) 應(yīng)該使用函數(shù) bzero() 或 memset() 來全部置零。 Also, and this is the important bit, a point

13、er to a struct sockaddr_in can be cast to a pointer to a struct sockaddr and vice-versa. 這樣的話 即使 socket() 想要的是 struct sockaddr *, 你仍然可以使用 struct sockaddr_in,and cast it at the last minute! 同時,注意 sin_family 和 struct sockaddr 中的 sa_family 一致并能夠設(shè)置為 AF_INET。最后, sin_port 和 sin_addr 必須是網(wǎng)絡(luò)字節(jié)順序 (Network Byt

14、e Order)!,Convert the Natives!,我們現(xiàn)在到達(dá)下個章節(jié)。我們曾經(jīng)講了很多網(wǎng)絡(luò)到本機(jī)字節(jié)順序,現(xiàn)在是采取行動的時刻了! 你能夠轉(zhuǎn)換兩種類型: short (兩個字節(jié))和 long (四個字節(jié))。這個 函數(shù)對于變量類型 unsigned 也適用。假設(shè)你想將 short 從本機(jī)字節(jié)順序 轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序。用 h 表示 本機(jī) (host),接著是 to,然后用 n 表示 網(wǎng)絡(luò) (network),最后用 s 表示 short: h-to-n-s, 或者 htons() (Host to Network Short)。 太簡單了. 如果不是太傻的話,你一定想到了組合 n,h

15、,s,和 l。但是這里沒有 stolh() (Short to Long Host) 函數(shù),但是這里有: htons()-Host to Network Short htonl()-Host to Network Long ntohs()-Network to Host Short ntohl()-Network to Host Long,IP 地址和如何處理他們,現(xiàn)在我們很幸運(yùn),因為我們有很多的函數(shù)來方便地操作 IP 地址。沒有必要用手工計算 他們,也沒有必要用 操作符來操作 long。 首先,假設(shè)你用 struct sockaddr_in ina,你想將 IP 地址

16、0 儲存到其中。你要用的函數(shù)是 inet_addr(),轉(zhuǎn)換 numbers-and-dots 格式的 IP 地址到 unsigned long。這個工作可以這樣來做: ina.sin_addr.s_addr = inet_addr(0); 注意:inet_addr() 返回的地址已經(jīng)是按照網(wǎng)絡(luò)字節(jié)順序的,你沒有必要再去調(diào)用 htonl()。 好了,你現(xiàn)在可以轉(zhuǎn)換字符串形式的 IP 地址為 long 了。那么你有一個數(shù)據(jù)結(jié)構(gòu) struct in_addr,該如何按照 numbers-and-dots 格式打印呢? 在這個 時候,也許你要用函數(shù) inet_ntoa() (n

17、toa 意思是 network to ascii): printf(%s,inet_ntoa(ina.sin_addr);,他將打印 IP 地址。注意的是:函數(shù) inet_ntoa() 的參數(shù)是 struct in_addr,而不是 long。同時要注意的是他返回的是一個指向字符的指針。 在 inet_ntoa 內(nèi)部的指針靜態(tài)地儲存字符數(shù)組,因此每次你調(diào)用 inet_ntoa() 的時候他將覆蓋以前的內(nèi)容。例如: char *a1, *a2; . . a1 = inet_ntoa(ina1.sin_addr); /* this is */ a2 = inet_ntoa

18、(ina2.sin_addr); /* this is 0 */ printf(address 1: %sn,a1); printf(address 2: %sn,a2); 運(yùn)行結(jié)果是: address 1: 0 address 2: 0 如果你想保存地址,那么用 strcpy() 保存到自己的字符數(shù)組中。,socket()-得到文件描述符!,我猜我不會再扯遠(yuǎn)了-我必須講 socket() 這個系統(tǒng)調(diào)用了。這里是詳細(xì)的定義: #include #include int socket(int domain, int type, i

19、nt protocol); 但是他們的參數(shù)怎么用? 首先,domain 應(yīng)該設(shè)置成 AF_INET,就象上面的 數(shù)據(jù)結(jié)構(gòu) struct sockaddr_in 中一樣。然后,參數(shù) type 告訴內(nèi)核是 SOCK_STREAM 類型還是 SOCK_DGRAM 類型。最后,把 protocol 設(shè)置為 0。(注意:有很多種 domain、type, 我不可能一一列出了,請看 socket() 的 man page。當(dāng)然,還有一個更好的方式 去得到 protocol。請看 getprotobyname() 的 man page。) socket() 只是返回你以后在系統(tǒng)調(diào)用種可能用到的 socket

20、 描述符,或者在錯誤 的時候返回-1。全局變量 errno 中儲存錯誤值。(請參考 perror() 的 man page。),bind()-我在哪個端口?,一旦你得到套接口,你可能要將套接口和機(jī)器上的一定的端口關(guān)聯(lián)起來。(如果你想用 listen() 來偵聽一定端口的數(shù)據(jù),這是必要一步-MUD 經(jīng)常告訴你說用命令 telnet x.y.z 6969.)如果你只想用 connect(),那么這個步驟沒有必要。但是無論如何,請繼續(xù)讀下去。 這里是系統(tǒng)調(diào)用 bind() 的大略: #include #include int bind(int sockfd, struct sockaddr *my_

21、addr, int addrlen); sockfd 是調(diào)用 socket 返回的文件描述符。my_addr 是指向 數(shù)據(jù)結(jié)構(gòu) struct sockaddr 的指針,他保存你的地址(即端口和 IP 地址) 信息。addrlen 設(shè)置為 sizeof(struct sockaddr)。,例子,#include #define MYPORT 3490 main() int sockfd; struct sockaddr_in my_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); /* do some error checking! */ my_ad

22、dr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(MYPORT); /* short, network byte order */ my_addr.sin_addr.s_addr = inet_addr(0); bzero(,這里也有要注意的幾件事情。my_addr.sin_port 是網(wǎng)絡(luò)字節(jié)順序,my_addr.sin_addr.s_addr 也是的。另外要注意到的事情是因系統(tǒng)的不同, 包含的頭文件也不盡相同,請查閱自己的 man page。 在 bind() 主題中最后要說

23、的話是,在處理自己的 IP 地址和/或端口的時候,有些工作 是可以自動處理的。 my_addr.sin_port = 0; /* choose an unused port at random */ my_addr.sin_addr.s_addr = INADDR_ANY; /* use my IP address */ 通過將0賦給 my_addr.sin_port,你告訴 bind() 自己選擇合適的端口。同樣, 將 my_addr.sin_addr.s_addr 設(shè)置為 INADDR_ANY,你告訴他自動填上 他所運(yùn)行的機(jī)器的 IP 地址。,bind() 在錯誤的時候依然是返回-1,并且

24、設(shè)置全局變量 errno。 在你調(diào)用 bind() 的時候,你要小心的另一件事情是:不要采用小于1024的端口號。所有小于1024的端口號都 被系統(tǒng)保留!你可以選擇從1024到65535(如果他們沒有被別的程序使用的話)。 你要注意的另外一件小事是:有時候你根本不需要調(diào)用他。如果你使用 connect() 來 和遠(yuǎn)程機(jī)器通訊,你不要關(guān)心你的本地端口號(就象你在使用 telnet 的時候),你只要 簡單的調(diào)用 connect() 就夠可,他會檢查套接口是否綁定,如果沒有,他會自己綁定 一個沒有使用的本地端口,connect()-Hello!,connect() 系統(tǒng)調(diào)用是這樣的: #includ

25、e #include int connect(int sockfd, struct sockaddr *serv_addr, int addrlen); sockfd 是系統(tǒng)調(diào)用 socket() 返回的套接口文件描述符。 serv_addr 是保存著目的地端口和 IP 地址的數(shù)據(jù)結(jié)構(gòu) struct sockaddr。 addrlen 設(shè)置為 sizeof(struct sockaddr)。,example,#include main() int sockfd; struct sockaddr_in dest_addr; /* will hold the destination addr */

26、 sockfd = socket(AF_INET, SOCK_STREAM, 0); /* dosomeerrorchecking! */ dest_addr.sin_family = AF_INET; /* host byte order */ dest_addr.sin_port = htons(23); /* short, network byte order */ dest_addr.sin_addr.s_addr = inet_addr(0); bzero(,listen(),int listen(int sockfd, int backlog); sockfd

27、 是調(diào)用 socket() 返回的套接口文件描述符。 backlog 是 在進(jìn)入隊列中允許的連接數(shù)目。是什么意思呢? 進(jìn)入的連接是在隊列中一直等待直到你接受 (accept() 請看下面的文章)的連接。他們的數(shù)目限制于隊列的允許。大多數(shù)系統(tǒng) 的允許數(shù)目是20,你也可以設(shè)置為5到10。 和別的函數(shù)一樣,在發(fā)生錯誤的時候返回-1,并設(shè)置全局變量 errno。,你可能想象到了,在你調(diào)用 listen() 前你或者要調(diào)用 bind() 或者讓 內(nèi)核隨便選擇一個端口。如果你想偵聽進(jìn)入的連接,那么系統(tǒng)調(diào)用的順序可能是這樣的: socket(); bind(); listen(); /* accept()

28、goes here */ 因為他相當(dāng)?shù)拿髁?,我將在這里不給出例子了。 (在 accept() 那一章的代碼將更加 完全。)真正麻煩的部分在 accept()。,accept(),準(zhǔn)備好了,系統(tǒng)調(diào)用 accept() 會有點(diǎn)古怪的地方的!你可以想象發(fā)生這樣的事情: 有人從很遠(yuǎn)的地方通過一個你在偵聽 (listen() 的端口連接 (connect() 到你的機(jī)器。他的連接將加入到等待接受 (accept() 的隊列中。你調(diào)用 accept() 告訴他你有空閑的連接。他將返回一個新的套接口文件描述符! 原來的一個還在偵聽你的那個端口,新的最后在準(zhǔn)備發(fā)送 (send() 和接收 ( recv() 數(shù)

29、據(jù)。這就是這個過程! 函數(shù)是這樣定義的: #include int accept(int sockfd, void *addr, int *addrlen); sockfd 相當(dāng)簡單,是和 listen() 中一樣的套接口描述符。addr 是個指向局部的數(shù)據(jù)結(jié)構(gòu) struct sockaddr_in 的指針。This is where the information about the incoming connection will go (and you can determine which host is calling you from which port). 在他的地址傳遞給 a

30、ccept 之前,addrlen 是個局部的整形變量,設(shè)置為 sizeof(struct sockaddr_in)。accept 將 不會將多余的字節(jié)給 addr。如果你放入的少些,那么在 addrlen 的值中反映 出來。,sockfd = socket(AF_INET, SOCK_STREAM, 0); /* do some error checking! */ my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(MYPORT); /* short, network byte order

31、*/ my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */ bzero( .,send() and recv(),這兩個函數(shù)用于流式套接口和數(shù)據(jù)報套接口的通訊。如果你喜歡使用無連接的數(shù)據(jù)報 套接口,你應(yīng)該看一看下面關(guān)于 sendto() 和 recvfrom() 的章節(jié)。 send() 是這樣的: int send(int sockfd, const void *msg, int len, int flags); sockfd 是你想發(fā)送數(shù)據(jù)的套接口描述符(或者是調(diào)用 socket() 或者是 accept() 返回的

32、。) msg 是指向你想發(fā)送的數(shù)據(jù)的指針。 len 是 數(shù)據(jù)的長度。 把 flags 設(shè)置為 0 就可以了。(詳細(xì)的資料請看 send() 的 man page)。,可能的例子,char *msg = Beej was here!; int len, bytes_sent; . . len = strlen(msg); bytes_sent = send(sockfd, msg, len, 0); .,recv() 函數(shù)很相似: int recv(int sockfd, void *buf, int len, unsigned int flags); sockfd 是要讀的套接口描述符。 bu

33、f 是要讀的信息的緩沖。len 是 緩沖的最大長度。 flags 也可以設(shè)置為0。(請參考recv() 的 man page。) recv() 返回實(shí)際讀入緩沖的數(shù)據(jù)的字節(jié)數(shù)?;蛘咴阱e誤的時候返回-1,同時設(shè)置 errno。,sendto() 和 recvfrom(),int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen); 你已經(jīng)看到了,除了另外的兩個信息外,其余的和函數(shù) send() 是一樣的。 to 是個指向數(shù)據(jù)結(jié)構(gòu) struct

34、sockaddr 的指針,他包含了目的地的 IP 地址和斷口信息。tolen 可以簡單地設(shè)置為 sizeof(struct sockaddr)。 相似的還有函數(shù) recv() 和 recvfrom()。 recvfrom() 的定義是 這樣的: int recvfrom(int sockfd, void *buf, int len, unsigned int flags struct sockaddr *from, int *fromlen);,close() 和 shutdown(),你已經(jīng)整天都在發(fā)送 (send() 和接收 (recv() 數(shù)據(jù)了,現(xiàn)在你準(zhǔn)備 關(guān)閉你的套接口描述符了。這很

35、簡單,你可以使用一般的 Unix 文件描述符的 close() 函 數(shù): close(sockfd); 他將防止套接口上更多的數(shù)據(jù)的讀寫。任何在另一端讀寫套接口的企圖都將返回錯誤信息。 如果你想在如何關(guān)閉套接口上有多一點(diǎn)的控制,你可以使用函數(shù) shutdown()。他能夠讓 你將一定方向的通訊或者雙向的通訊(就象 close() 一樣)關(guān)閉,你可以使用: int shutdown(int sockfd, int how);,sockfd 是你想要關(guān)閉的套接口文件描述復(fù)。how 的值是下面的其中之一: 0 - Further receives are disallowed 1 - Further

36、 sends are disallowed 2 - Further sends and receives are disallowed (和 close() 一樣 shutdown() 成功時返回 0,失敗時返回 -1(同時設(shè)置 errno。) 如果在無連接的數(shù)據(jù)報套接口中使用 shutdown(),那么只不過是讓 send() 和 recv() 不能使用(記得你在數(shù)據(jù)報套接口中使用了 connect 后是可以 使用他們的嗎?),getpeername()-Who are you?,函數(shù) getpeername() 告訴你在連接的流式套接口上誰在另外一邊。函數(shù)是這樣的: #include in

37、t getpeername(int sockfd, struct sockaddr *addr, int *addrlen); sockfd 是連接的流式套接口的描述符。 addr 是一個指向結(jié)構(gòu) struct sockaddr (或者是 struct sockaddr_in) 的指針,他保存著 連接的另一邊的信息。 addrlen 是一個 int 型的指針,他初始化為 sizeof(struct sockaddr)。 函數(shù)在錯誤的時候返回 -1,設(shè)置相應(yīng)的 errno。,gethostname()-Who am I?,甚至比 getpeername() 還簡單的函數(shù)是 gethostname

38、()。他返回你程序 所運(yùn)行的機(jī)器的主機(jī)名字。然后你可以使用 gethostbyname() 以獲得你的機(jī)器的 IP 地址。 下面是定義: #include nt gethostname(char *hostname, size_t size); 參數(shù)很簡單: hostname 是一個字符數(shù)組指針,他將在函數(shù)返回時保存 主機(jī)名。size 是 hostname 數(shù)組的字節(jié)長度。 函數(shù)調(diào)用成功時返回 0,失敗時返回 -1,并設(shè)置 errno。,DNS,You say , I say 00 如果你不知道 DNS 的意思,那么我告訴你,他代表域名服務(wù) (Domain Name Service)。 他主要的功能是:你給他一個容易記憶的某站點(diǎn)的地址,他給你 IP 地址(然后你就可以 使用 bind(), connect(), sendto() 或者其他函數(shù)。)當(dāng)一個人 輸入: $ telnet telnet 能知道他將連接 (connect() 到 00。,但是這是如何工作的呢? 你可以調(diào)用函數(shù) gethostbyname(): #include struct hostent *gethostbyname(const char *name); 很明白的是,他返回一

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

最新文檔

評論

0/150

提交評論