UNIX網(wǎng)絡(luò)程序設(shè)計(jì)_第1頁(yè)
UNIX網(wǎng)絡(luò)程序設(shè)計(jì)_第2頁(yè)
UNIX網(wǎng)絡(luò)程序設(shè)計(jì)_第3頁(yè)
UNIX網(wǎng)絡(luò)程序設(shè)計(jì)_第4頁(yè)
UNIX網(wǎng)絡(luò)程序設(shè)計(jì)_第5頁(yè)
已閱讀5頁(yè),還剩55頁(yè)未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡(jiǎn)介

1、 介紹在介紹在UNIX環(huán)境下,如何使用套接字環(huán)境下,如何使用套接字API編寫(xiě)網(wǎng)絡(luò)應(yīng)用程編寫(xiě)網(wǎng)絡(luò)應(yīng)用程序。大部分網(wǎng)絡(luò)應(yīng)用系統(tǒng)都可以分為客戶端(序。大部分網(wǎng)絡(luò)應(yīng)用系統(tǒng)都可以分為客戶端(client)和服務(wù)器)和服務(wù)器端(端(server),就是通常所說(shuō)的),就是通常所說(shuō)的C/S結(jié)構(gòu),最典型也最常見(jiàn)的,結(jié)構(gòu),最典型也最常見(jiàn)的,上網(wǎng)就是一種上網(wǎng)就是一種C/S模式的應(yīng)用,瀏覽器模式的應(yīng)用,瀏覽器ie是客戶端,是客戶端,web服務(wù)器服務(wù)器作為服務(wù)器端。作為服務(wù)器端。 網(wǎng)間進(jìn)程通信網(wǎng)間進(jìn)程通信網(wǎng)間進(jìn)程通信要解決的是不同主機(jī)進(jìn)程間的相互通信問(wèn)題(可把同機(jī)進(jìn)程通信看作是其中的特例)。為此,首先要解決的是網(wǎng)間進(jìn)程

2、標(biāo)識(shí)問(wèn)題。同一主機(jī)上,不同進(jìn)程可用進(jìn)程號(hào)(process ID)唯一標(biāo)識(shí)。但在網(wǎng)絡(luò)環(huán)境下,各主機(jī)獨(dú)立分配的進(jìn)程號(hào)不能唯一標(biāo)識(shí)該進(jìn)程。 其次,操作系統(tǒng)支持的網(wǎng)絡(luò)協(xié)議眾多,不同協(xié)議的工作方式不同,地址格式也不同。因此,網(wǎng)間進(jìn)程通信還要解決多重協(xié)議的識(shí)別問(wèn)題。 端口端口端口是一種抽象的軟件結(jié)構(gòu)(包括一些數(shù)據(jù)結(jié)構(gòu)和I/O緩沖區(qū))。應(yīng)用程序(即進(jìn)程)通過(guò)系統(tǒng)調(diào)用與某端口建立連接(binding)后,傳輸層傳給該端口的數(shù)據(jù)都被相應(yīng)進(jìn)程所接收,相應(yīng)進(jìn)程發(fā)給傳輸層的數(shù)據(jù)都通過(guò)該端口輸出。在TCP/IP協(xié)議的實(shí)現(xiàn)中,端口操作類似于一般的I/O操作,進(jìn)程獲取一個(gè)端口,相當(dāng)于獲取本地唯一的I/O文件,可以用一般的讀

3、寫(xiě)原語(yǔ)訪問(wèn)。 端口端口端口號(hào)的分配有兩種基本分配方式:全局分配;本地分配TCP/IP端口號(hào)的分配中綜合了上述兩種方式。TCP/IP將端口號(hào)分為兩部分,少量的作為保留端口,以全局方式分配給服務(wù)進(jìn)程。因此,每一個(gè)標(biāo)準(zhǔn)服務(wù)器都擁有一個(gè)全局公認(rèn)的端口(即周知口,well-known port),即使在不同機(jī)器上,其端口號(hào)也相同。剩余的為自由端口,以本地方式進(jìn)行分配。 地址地址 網(wǎng)絡(luò)通信中通信的兩個(gè)進(jìn)程分別在不同的機(jī)器上。在互連網(wǎng)絡(luò)中,兩臺(tái)機(jī)器可能位于不同的網(wǎng)絡(luò),這些網(wǎng)絡(luò)通過(guò)網(wǎng)絡(luò)互連設(shè)備(網(wǎng)關(guān),網(wǎng)橋,路由器等)連接。因此需要三級(jí)尋址:1. 某一主機(jī)可與多個(gè)網(wǎng)絡(luò)相連,必須指定一特定網(wǎng)絡(luò)地址;2. 網(wǎng)絡(luò)上每

4、一臺(tái)主機(jī)應(yīng)有其唯一的地址;3. 每一主機(jī)上的每一進(jìn)程應(yīng)有在該主機(jī)上的唯一標(biāo)識(shí)符。 通常主機(jī)地址由網(wǎng)絡(luò)ID和主機(jī)ID組成,在TCP/IP協(xié)議中用32位整數(shù)值表示;TCP和UDP均使用16位端口號(hào)標(biāo)識(shí)用戶進(jìn)程。 網(wǎng)絡(luò)字節(jié)順序 不同的計(jì)算機(jī)存放多字節(jié)值的順序不同,因此為保證數(shù)據(jù)的正確性,在網(wǎng)絡(luò)協(xié)議中須指定網(wǎng)絡(luò)字節(jié)順序。TCP/IP協(xié)議使用16位整數(shù)和32位整數(shù)的高價(jià)先存格式。 連接 兩個(gè)進(jìn)程間的通信鏈路稱為連接。連接在內(nèi)部表現(xiàn)為一些緩沖區(qū)和一組協(xié)議機(jī)制,在外部表現(xiàn)出比無(wú)連接高的可靠性。n 半相關(guān) 網(wǎng)絡(luò)中用一個(gè)三元組可以在全局唯一標(biāo)志一個(gè)進(jìn)程: (協(xié)議,本地地址,本地端口號(hào)) 這樣一個(gè)三元組,叫做一個(gè)

5、半相關(guān)(half-association),它指定連接的每半部分。n 全相關(guān) 一個(gè)完整的網(wǎng)間進(jìn)程通信需要由兩個(gè)進(jìn)程組成,并且只能使用同一種高層協(xié)議。因此一個(gè)完整的網(wǎng)間通信需要一個(gè)五元組來(lái)標(biāo)識(shí): (協(xié)議,本地地址,本地端口號(hào),遠(yuǎn)地地址,遠(yuǎn)地端口號(hào)) 這樣一個(gè)五元組,叫做一個(gè)相關(guān)(association),即兩個(gè)協(xié)議相同的半相關(guān)才能組合成一個(gè)合適的相關(guān),或完全指定組成一連接。 服務(wù)方式:面向連接服務(wù),無(wú)連接服務(wù)面向連接服務(wù) 面向連接服務(wù)是電話系統(tǒng)服務(wù)模式的抽象,即每一次完整的數(shù)據(jù)傳輸都要經(jīng)過(guò)建立連接,使用連接,終止連接的過(guò)程。在數(shù)據(jù)傳輸過(guò)程中,各數(shù)據(jù)分組不攜帶目的地址,而使用連接號(hào)。本質(zhì)上,連接是

6、一個(gè)管道,收發(fā)數(shù)據(jù)不但順序一致,而且內(nèi)容相同。TCP協(xié)議提供面向連接的虛電路。無(wú)連接服務(wù) 無(wú)連接服務(wù)是郵政系統(tǒng)服務(wù)的抽象,每個(gè)分組都攜帶完整的目的地址,各分組在系統(tǒng)中獨(dú)立傳送。無(wú)連接服務(wù)不能保證分組的先后順序,不進(jìn)行分組出錯(cuò)的恢復(fù)與重傳,不保證傳輸?shù)目煽啃?。UDP協(xié)議提供無(wú)連接的數(shù)據(jù)報(bào)服務(wù)。n 客戶/服務(wù)器模式 服務(wù)器方: 1. 打開(kāi)一通信通道并告知本地主機(jī),它愿意在某一公認(rèn)地址上(周知口,如FTP為21)接收客戶請(qǐng)求; 2. 等待客戶請(qǐng)求到達(dá)該端口; 3. 接收到重復(fù)服務(wù)請(qǐng)求,處理該請(qǐng)求并發(fā)送應(yīng)答信號(hào)。接收到并發(fā)服務(wù)請(qǐng)求,要激活一新進(jìn)程來(lái)處理這個(gè)客戶請(qǐng)求(如UNIX系統(tǒng)中用fork、exec

7、)。新進(jìn)程處理此客戶請(qǐng)求,并不需要對(duì)其它請(qǐng)求作出應(yīng)答。服務(wù)完成后,關(guān)閉此新進(jìn)程與客戶的通信鏈路,并終止。 4. 返回第二步,等待另一客戶請(qǐng)求。 5. 關(guān)閉服務(wù)器l 客戶方: 1. 打開(kāi)一通信通道,并連接到服務(wù)器所在主機(jī)的特定端口; 2. 向服務(wù)器發(fā)服務(wù)請(qǐng)求報(bào)文,等待并接收應(yīng)答;繼續(xù)提出請(qǐng)求. 3. 請(qǐng)求結(jié)束后關(guān)閉通信通道并終止。1. 套接字的經(jīng)典定義套接字的經(jīng)典定義 Linux系統(tǒng)是通過(guò)提供套接字系統(tǒng)是通過(guò)提供套接字(socket)來(lái)進(jìn)行網(wǎng)絡(luò)編程的來(lái)進(jìn)行網(wǎng)絡(luò)編程的.網(wǎng)絡(luò)網(wǎng)絡(luò)程序通過(guò)程序通過(guò)socket和其它幾個(gè)函數(shù)的調(diào)用和其它幾個(gè)函數(shù)的調(diào)用,會(huì)返回一個(gè)會(huì)返回一個(gè) 通訊的文件描通訊的文件描述符述

8、符,我們可以將這個(gè)描述符看成普通的文件的描述符來(lái)操作我們可以將這個(gè)描述符看成普通的文件的描述符來(lái)操作,這就是這就是linux的設(shè)備無(wú)關(guān)性的的設(shè)備無(wú)關(guān)性的 好處好處.我們可以通過(guò)向描述符讀寫(xiě)操作實(shí)現(xiàn)網(wǎng)我們可以通過(guò)向描述符讀寫(xiě)操作實(shí)現(xiàn)網(wǎng)絡(luò)之間的數(shù)據(jù)交流絡(luò)之間的數(shù)據(jù)交流. 從用戶的角度來(lái)看,套接字是網(wǎng)絡(luò)通信端點(diǎn)的一種抽象概念,它從用戶的角度來(lái)看,套接字是網(wǎng)絡(luò)通信端點(diǎn)的一種抽象概念,它為用戶提供了一種在網(wǎng)絡(luò)上發(fā)送和接收數(shù)據(jù)的機(jī)制。為用戶提供了一種在網(wǎng)絡(luò)上發(fā)送和接收數(shù)據(jù)的機(jī)制。2. 套接字的域套接字的域, 類型類型 和和 協(xié)議協(xié)議 域域 說(shuō)明我們網(wǎng)絡(luò)程序所在的主機(jī)采用的說(shuō)明我們網(wǎng)絡(luò)程序所在的主機(jī)采用的(

9、AF_UNIX (AF_UNIX 或或 AF_INET)AF_INET) 類型類型 說(shuō)明套接字類型,可以是說(shuō)明套接字類型,可以是 SOCK_STREAM, SOCK_DGRAM SOCK_STREAM, SOCK_DGRAM 或或 SOCK_RAWSOCK_RAW 協(xié)議協(xié)議 指定套接字使用的協(xié)議指定套接字使用的協(xié)議當(dāng)新創(chuàng)建一個(gè)套接字時(shí),需要指定上述當(dāng)新創(chuàng)建一個(gè)套接字時(shí),需要指定上述3 3個(gè)特性個(gè)特性3.創(chuàng)建套接字創(chuàng)建套接字用戶需要進(jìn)行任何網(wǎng)絡(luò)通信時(shí),需要?jiǎng)?chuàng)建一個(gè)套接字用戶需要進(jìn)行任何網(wǎng)絡(luò)通信時(shí),需要?jiǎng)?chuàng)建一個(gè)套接字#include int socket(int domain, int type,

10、int protocol);domain:網(wǎng)絡(luò)程序所在的主機(jī)采用的通訊協(xié)族網(wǎng)絡(luò)程序所在的主機(jī)采用的通訊協(xié)族(AF_UNIX和和AF_INET等等). AF_UNIX只能夠用于單一的只能夠用于單一的Unix系統(tǒng)進(jìn)程間通信系統(tǒng)進(jìn)程間通信,而而AF_INET是針是針對(duì)對(duì)Internet的的,因而可以允許在遠(yuǎn)程主機(jī)之間通信因而可以允許在遠(yuǎn)程主機(jī)之間通信type:網(wǎng)絡(luò)程序所采用的通訊協(xié)議網(wǎng)絡(luò)程序所采用的通訊協(xié)議(SOCK_STREAM,SOCK_DGRAM等等) SOCK_STREAM表明用的是表明用的是TCP協(xié)議協(xié)議,這樣會(huì)提供按順序的這樣會(huì)提供按順序的,可靠可靠,雙向雙向,面面向連接的比特流向連接的

11、比特流. SOCK_DGRAM表明用的是表明用的是UDP協(xié)議協(xié)議,這樣只會(huì)提供定長(zhǎng)這樣只會(huì)提供定長(zhǎng)的的,不可靠不可靠,無(wú)連接的通信無(wú)連接的通信.protocol:由于指定了由于指定了type,所以這個(gè)地方一般只要用所以這個(gè)地方一般只要用0來(lái)代替就可以了來(lái)代替就可以了 sock et為網(wǎng)絡(luò)通訊做基本的準(zhǔn)備為網(wǎng)絡(luò)通訊做基本的準(zhǔn)備.成功時(shí)返回文件描述符成功時(shí)返回文件描述符,失敗時(shí)返回失敗時(shí)返回-13.創(chuàng)建套接字創(chuàng)建套接字#include int sockfd;sockfd = socket( AF_INET, SOCK_STREAM, 0 );4.關(guān)閉套接字關(guān)閉套接字#include int clo

12、se(int sockfd);套接字名字套接字名字 = 套接地址套接地址UNIX域域 : 文件路徑名文件路徑名套接字文件套接字文件(一種特殊文件一種特殊文件)internet域域 : 主機(jī)主機(jī)IP+ 端口號(hào)端口號(hào)1.1.主機(jī)的主機(jī)的IPIP地址地址 在在IPIP網(wǎng)絡(luò)中,每臺(tái)機(jī)器都有一個(gè)網(wǎng)絡(luò)中,每臺(tái)機(jī)器都有一個(gè) IP IP 地址,一個(gè)地址,一個(gè)3232位的數(shù)字,位的數(shù)字,它唯一地標(biāo)識(shí)這臺(tái)機(jī)器。它唯一地標(biāo)識(shí)這臺(tái)機(jī)器。 通常通常,32,32位的位的IPIP地址可以由四個(gè)用點(diǎn)分開(kāi)的數(shù)字表示,每個(gè)數(shù)字地址可以由四個(gè)用點(diǎn)分開(kāi)的數(shù)字表示,每個(gè)數(shù)字都是一個(gè)都是一個(gè)8 8位長(zhǎng)的整數(shù)位長(zhǎng)的整數(shù), ,例如例如16.

13、42.0.9。主機(jī)的主機(jī)的IPIP地址地址 : : 特殊特殊IPIP地址地址 在在UNIXUNIX系統(tǒng)中系統(tǒng)中, ,定義了一些具有特殊意義的定義了一些具有特殊意義的IPIP地址地址, ,聲明在頭文件聲明在頭文件中中 INADDR_LOOPBACK INADDR_LOOPBACK 表示本機(jī)器地址表示本機(jī)器地址, ,統(tǒng)一定義為統(tǒng)一定義為 INADDR_BROADCAST INADDR_BROADCAST 廣播地址廣播地址, ,用來(lái)進(jìn)行消息廣播的特定地址用來(lái)進(jìn)行消息廣播的特定地址 INADDR_ANY INADDR_ANY 通配名通配名(a) (

14、a) 主機(jī)的主機(jī)的IPIP地址地址/ IP地址的內(nèi)部表示地址的內(nèi)部表示:#include struct in_addr in_addr_t s_addr; 32位無(wú)符號(hào)整數(shù)位無(wú)符號(hào)整數(shù)(a) (a) 主機(jī)的主機(jī)的IPIP地址地址字符串字符串IP和和32位位IP地址轉(zhuǎn)換函數(shù)地址轉(zhuǎn)換函數(shù)int inet_aton (char *name, struct in_addr *addr);char* inet_ntoa (struct in_addr in);函數(shù)里面函數(shù)里面 a 代表代表 ascii n 代表代表network.第一個(gè)函數(shù)表示將第一個(gè)函數(shù)表示將a.b.c.d的的IP轉(zhuǎn)換為轉(zhuǎn)換為32位的

15、位的IP,存儲(chǔ)在存儲(chǔ)在 inp指針里面指針里面.第二個(gè)是將第二個(gè)是將32位位IP轉(zhuǎn)換為轉(zhuǎn)換為a.b.c.d的格式的格式.(b) (b) 主機(jī)名主機(jī)名 為了方便記憶,計(jì)算機(jī)都有一個(gè)主機(jī)名,這樣就不用記復(fù)雜的數(shù)點(diǎn)為了方便記憶,計(jì)算機(jī)都有一個(gè)主機(jī)名,這樣就不用記復(fù)雜的數(shù)點(diǎn)形式的形式的IPIP地址地址 在目前所有的操作系統(tǒng)中都有一個(gè)在目前所有的操作系統(tǒng)中都有一個(gè)hostshosts文件,用于記錄主機(jī)名和文件,用于記錄主機(jī)名和數(shù)點(diǎn)形式的數(shù)點(diǎn)形式的IPIP地址的映射。地址的映射。 UNIX UNIX系統(tǒng)為處理主機(jī)信息,定義了系統(tǒng)為處理主機(jī)信息,定義了 hostent hostent 結(jié)構(gòu)描述主機(jī)名相關(guān)信息

16、結(jié)構(gòu)描述主機(jī)名相關(guān)信息include struct hostent char * h_name; /* 主機(jī)的正式名稱主機(jī)的正式名稱 */ char * h_aliases; /* 主機(jī)的別名主機(jī)的別名 */ int h_addrtype; /* 主機(jī)的地址類型主機(jī)的地址類型 AF_INET*/ int h_length; /* 主機(jī)的地址長(zhǎng)度主機(jī)的地址長(zhǎng)度 對(duì)于對(duì)于IP4 是是4字節(jié)字節(jié)32位位*/ char * h_addr_list; /* 主機(jī)的主機(jī)的IP地址列表地址列表 */#define h_addr h_addr_list0 /* 主機(jī)的第一個(gè)IP地址*/ UNIX UNIX系統(tǒng)

17、為獲得主機(jī)信息的相關(guān)函數(shù)系統(tǒng)為獲得主機(jī)信息的相關(guān)函數(shù)#include struct hostent* gethostbyname( char *name);struct hostent* gethostbyaddr( void *addr, size_t length, int type ); gethostbyname可以將機(jī)器名可以將機(jī)器名(如如 )轉(zhuǎn)換為一個(gè)轉(zhuǎn)換為一個(gè)結(jié)構(gòu)指針結(jié)構(gòu)指針.在這個(gè)結(jié)構(gòu)里面儲(chǔ)存了域名的信息在這個(gè)結(jié)構(gòu)里面儲(chǔ)存了域名的信息 gethostbyaddr可以將一個(gè)可以將一個(gè)32位的位的IP地址地址(C0A80001)轉(zhuǎn)換為結(jié)構(gòu)轉(zhuǎn)換為結(jié)構(gòu)指針指針. 這兩個(gè)函數(shù)失敗時(shí)返回這

18、兩個(gè)函數(shù)失敗時(shí)返回NULL.2.2.服務(wù)與端口服務(wù)與端口套接字地址套接字地址 機(jī)器的機(jī)器的IPIP地址地址 端口號(hào)端口號(hào)標(biāo)識(shí)一臺(tái)計(jì)算機(jī)標(biāo)識(shí)一臺(tái)計(jì)算機(jī)區(qū)別同一臺(tái)計(jì)算機(jī)上區(qū)別同一臺(tái)計(jì)算機(jī)上的不同服務(wù)程序的不同服務(wù)程序2 2 服務(wù)與端口服務(wù)與端口UNIXUNIX系統(tǒng)中的端口分配系統(tǒng)中的端口分配 0 0, 不使用不使用 1 110231023, 知名端口知名端口( (保留端口保留端口) ),限定為標(biāo)準(zhǔn)服務(wù)使用,如,限定為標(biāo)準(zhǔn)服務(wù)使用,如ftp ftp 的的2121端口,端口,httphttp的的8080端口等端口等 1024 102450005000,可以被任意的客戶端程序使用,可以被任意的客戶端程序

19、使用 5001 50016553565535,為其他服務(wù)程序預(yù)留,為其他服務(wù)程序預(yù)留 UNIX UNIX系統(tǒng)為處理服務(wù)信息,定義了系統(tǒng)為處理服務(wù)信息,定義了 servent servent 結(jié)構(gòu)描述服務(wù)相關(guān)信息結(jié)構(gòu)描述服務(wù)相關(guān)信息include struct servent char * s_name; /服務(wù)的正式名稱服務(wù)的正式名稱 char* s_aliases; /服務(wù)的可選別名服務(wù)的可選別名 int s_port; /服務(wù)使用的端口號(hào)服務(wù)使用的端口號(hào) char * s_proto; /與該服務(wù)一起使用的協(xié)議名與該服務(wù)一起使用的協(xié)議名 UNIX UNIX系統(tǒng)為獲得服務(wù)信息的相關(guān)函數(shù)系統(tǒng)為

20、獲得服務(wù)信息的相關(guān)函數(shù)#include struct servent* getservbyname(char *name,char* proto);Struct servent* getservbyport(int port, char* proto);不同的計(jì)算機(jī)系統(tǒng)采用不同的字節(jié)序存儲(chǔ)數(shù)據(jù)不同的計(jì)算機(jī)系統(tǒng)采用不同的字節(jié)序存儲(chǔ)數(shù)據(jù)Little-EndianLittle-Endian字節(jié)序字節(jié)序: :將低字節(jié)存儲(chǔ)在起始地址將低字節(jié)存儲(chǔ)在起始地址, ,由由IntelIntel體系采用體系采用Big-EndianBig-Endian字節(jié)序字節(jié)序: :將高字節(jié)存儲(chǔ)在起始地址將高字節(jié)存儲(chǔ)在起始地址,

21、,由由MacintoshMacintosh體系采用體系采用內(nèi)存地址增大方向內(nèi)存地址增大方向地址A地址A+107010107Big-EndianBig-EndianLittle-EndianLittle-Endian1616位整數(shù)位整數(shù)0 x01070 x0107主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序主機(jī)字節(jié)序主機(jī)字節(jié)序: :將某給定系統(tǒng)所用的字節(jié)序稱為主機(jī)字節(jié)序?qū)⒛辰o定系統(tǒng)所用的字節(jié)序稱為主機(jī)字節(jié)序網(wǎng)絡(luò)字節(jié)序網(wǎng)絡(luò)字節(jié)序: :網(wǎng)絡(luò)上傳輸?shù)臄?shù)據(jù)使用規(guī)定的字節(jié)序網(wǎng)絡(luò)上傳輸?shù)臄?shù)據(jù)使用規(guī)定的字節(jié)序, ,即網(wǎng)絡(luò)字節(jié)序即網(wǎng)絡(luò)字節(jié)序, ,采用采用big-endianbig-endian主機(jī)字節(jié)序和網(wǎng)絡(luò)字

22、節(jié)序的轉(zhuǎn)換主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序的轉(zhuǎn)換UNIXUNIX系統(tǒng)中提供了一組函數(shù)用來(lái)進(jìn)行網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序的轉(zhuǎn)換系統(tǒng)中提供了一組函數(shù)用來(lái)進(jìn)行網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序的轉(zhuǎn)換#include uint16_t htons ( uint16_t hostshort );uint32_t htonl ( uint32_t hostlong );uint16_t ntohs ( uint16_t netshort );uint32_t ntohl ( uint32_t netlong ); 其中其中h 代表代表host, n 代表代表 network.s 代表代表short l 代表代表long 第一個(gè)函第

23、一個(gè)函數(shù)的意義是將本機(jī)器上的數(shù)的意義是將本機(jī)器上的long數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)上的數(shù)據(jù)轉(zhuǎn)化為網(wǎng)絡(luò)上的long. 其他幾個(gè)函數(shù)的其他幾個(gè)函數(shù)的意義也差不多意義也差不多 套接字地址的數(shù)據(jù)結(jié)構(gòu)套接字地址的數(shù)據(jù)結(jié)構(gòu)Internet通信域地址數(shù)據(jù)結(jié)構(gòu)通信域地址數(shù)據(jù)結(jié)構(gòu):#include struct sockaddr unisgned short as_family;/地址協(xié)議族地址協(xié)議族,為為 AF_INET char sa_data14; /保留未用保留未用 ;套接字地址的數(shù)據(jù)結(jié)構(gòu)套接字地址的數(shù)據(jù)結(jié)構(gòu)Internet通信域地址數(shù)據(jù)結(jié)構(gòu)通信域地址數(shù)據(jù)結(jié)構(gòu):#include struct sockaddr_i

24、n sa_family_t sin_family; /地址協(xié)議族地址協(xié)議族,為為 AF_INET in_port_t sin_port; /主機(jī)端口號(hào)主機(jī)端口號(hào) struct in_addr sin_addr; /主機(jī)的主機(jī)的internet地址地址 unsigned char sin_zero; /保留未用保留未用示例示例 構(gòu)造一個(gè)構(gòu)造一個(gè)internetinternet套接字地址套接字地址流程流程sock = socket(AF_INET, SOCK_STREAM, 0 );struct sockaddr_in name ;3.init_sockaddr( &name, “”, “

25、12345”);#include void init_sockaddr(struct sockaddr_in *name, char* hostname, char * serv) struct hostent *hp; char *host, myname256; if( hostname = null ) gethostname(myname, sizeof(myname); host = myname; else host = hostname; hp = gethostbyname( host ); bzero( name, sizeof( struct sockaddr ) ); i

26、f( hp-h_addrtype = AF_INET ) name-sin_family = AF_INET; bcopy( hp-h_addr_list0,&name-sin_addr, hp-length); if( serv = = null ) name-sin_port = htons(0); else name-sin_port = htons( atoi(serv); else printf(“UNKNOWN ADDRESS TYPE !”);命名套接字命名套接字調(diào)用調(diào)用socketsocket函數(shù)創(chuàng)建套接字僅返回一個(gè)套接字描述符函數(shù)創(chuàng)建套接字僅返回一個(gè)套接字描述符, ,

27、沒(méi)有地址信息沒(méi)有地址信息套接字必須與地址綁定套接字必須與地址綁定, ,才能被其他進(jìn)程所訪問(wèn)才能被其他進(jìn)程所訪問(wèn), ,因此需要對(duì)套接字命名因此需要對(duì)套接字命名命名函數(shù)命名函數(shù)#include int bind( int socket, struct sockaddr *address, socklen_t address_len ); sockfd:是由是由socket調(diào)用返回的文件描述符調(diào)用返回的文件描述符. my_addr:是一個(gè)指向是一個(gè)指向sockaddr的指針的指針 addrlen:是是sockaddr結(jié)構(gòu)的長(zhǎng)度結(jié)構(gòu)的長(zhǎng)度.UNIXUNIX域和域和internetinternet域都使

28、用域都使用bindbind函數(shù)來(lái)設(shè)置套接字地址函數(shù)來(lái)設(shè)置套接字地址, ,因此使用通用因此使用通用地址結(jié)構(gòu)地址結(jié)構(gòu) struct sockaddr ,對(duì)于網(wǎng)絡(luò)通信對(duì)于網(wǎng)絡(luò)通信,必須用必須用sockaddr_in構(gòu)構(gòu)造一個(gè)地址造一個(gè)地址,當(dāng)調(diào)用當(dāng)調(diào)用bind時(shí)時(shí),將類型強(qiáng)制轉(zhuǎn)換成將類型強(qiáng)制轉(zhuǎn)換成 struct sockaddr示例示例: :#include void make_socket( unsigned short int port ) int i,sock; struct sockaddr_in address; sock = socket( AF_INET, SOCK_STREAM, 0

29、); address.sin_family = AF_INET; address.sin_port = htons( port ); address.sin_addr.s_addr = htonl( INADDR_ANY ); i = bind( sock, (struct sockaddr*)&address, sizeof(address); if( i 0 ) exit(1); return sock; 示例說(shuō)明示例說(shuō)明: : 函數(shù)函數(shù)make_socket不同于前面的不同于前面的init_socket,它沒(méi)有查找和使用它沒(méi)有查找和使用機(jī)器的機(jī)器的internet地址地址,而是使

30、用通配名而是使用通配名INADDR_ANY作為套接字的地作為套接字的地址址.系統(tǒng)解釋這個(gè)地址為程序運(yùn)行所在機(jī)器的任意合法的網(wǎng)絡(luò)地址系統(tǒng)解釋這個(gè)地址為程序運(yùn)行所在機(jī)器的任意合法的網(wǎng)絡(luò)地址,這這種類型的套接字可以在機(jī)器的不同種類型的套接字可以在機(jī)器的不同ip地址上提供服務(wù)地址上提供服務(wù). 函數(shù)函數(shù)make_socket的參數(shù)的參數(shù)port和通配名常數(shù)和通配名常數(shù)INADDR_ANY都是主機(jī)都是主機(jī)字節(jié)順序字節(jié)順序,在填入在填入sockaddr_in時(shí)時(shí),需要轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序需要轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序.示例示例: :#include void make_socket( unsigned short i

31、nt port, char *ipaddress ) int i,sock; struct sockaddr_in address; sock = socket( AF_INET, SOCK_STREAM, 0); address.sin_family = AF_INET; address.sin_port = htons( port ); inet_aton( ipaddress, &address.sin_addr); i = bind( sock, (struct sockaddr*)&address, sizeof(address); if( i 0 ) exit(1)

32、; return sock; 通信模式通信模式 同一臺(tái)計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以同一臺(tái)計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以 有連接有連接 模式使用套接字模式使用套接字, ,套接字類型為套接字類型為SOCK_STREAM ,SOCK_STREAM ,這種模式稱為面向連接的這種模式稱為面向連接的c/sc/s模式模式, ,使用協(xié)使用協(xié)議議TCPTCP 不同計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以不同計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以 有連接有連接 模式使用套接字模式使用套接字, , 模模式式1 1的網(wǎng)絡(luò)擴(kuò)展的網(wǎng)絡(luò)擴(kuò)展 同一臺(tái)計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以同一臺(tái)計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以 無(wú)連接無(wú)連接 方式使用套

33、接字方式使用套接字, ,套接字類型為套接字類型為 SOCK_DGRAM,SOCK_DGRAM,使用協(xié)議使用協(xié)議UDPUDP 不同計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以無(wú)連接模式使用套接字不同計(jì)算機(jī)中的客戶和服務(wù)進(jìn)程之間以無(wú)連接模式使用套接字, , 模式模式3 3的網(wǎng)絡(luò)擴(kuò)展的網(wǎng)絡(luò)擴(kuò)展流套接字通信模式流套接字通信模式socketbindlistenaccept阻塞直到收到阻塞直到收到來(lái)自客戶的連接來(lái)自客戶的連接readwriteclosesocketconnectwrite應(yīng)用邏輯應(yīng)用邏輯readclose應(yīng)用邏輯應(yīng)用邏輯連接建立連接建立數(shù)據(jù)數(shù)據(jù)(請(qǐng)求請(qǐng)求)數(shù)據(jù)數(shù)據(jù)(應(yīng)答應(yīng)答)數(shù)據(jù)報(bào)套接字通信模式數(shù)據(jù)報(bào)套

34、接字通信模式socketbindrecvfrom阻塞直到收到阻塞直到收到來(lái)自客戶的數(shù)據(jù)報(bào)來(lái)自客戶的數(shù)據(jù)報(bào)sendtosocketsendto應(yīng)用邏輯應(yīng)用邏輯recvfromclose數(shù)據(jù)數(shù)據(jù)(請(qǐng)求請(qǐng)求)數(shù)據(jù)數(shù)據(jù)(應(yīng)答應(yīng)答)通信模式通信模式最常見(jiàn)的流套接字通信模式是與另一個(gè)特定的套接字建立連接最常見(jiàn)的流套接字通信模式是與另一個(gè)特定的套接字建立連接, ,然后然后與那個(gè)套接字一次又一次地交換數(shù)據(jù)與那個(gè)套接字一次又一次地交換數(shù)據(jù)請(qǐng)求連接請(qǐng)求連接 請(qǐng)求連接是客戶端的動(dòng)作請(qǐng)求連接是客戶端的動(dòng)作. . 客戶端套接字是主動(dòng)套接字客戶端套接字是主動(dòng)套接字, ,客戶進(jìn)程通過(guò)調(diào)用客戶進(jìn)程通過(guò)調(diào)用connectcon

35、nect函數(shù)建立與函數(shù)建立與有名的套接字的連接有名的套接字的連接請(qǐng)求連接請(qǐng)求連接#include int connect(int sockfd, struct sockaddr *serv_addr, socklen_t serv_len );sockfd:socket返回的文件描述符.serv_addr:儲(chǔ)存了服務(wù)器端的連接信息.其中sin_add是服務(wù)端的地址serv_len:serv_addr的長(zhǎng)度 connect函數(shù)是客戶端用來(lái)同服務(wù)端連接的.成功時(shí)返回0,sockfd是同服務(wù)端通訊的文件描述符失敗時(shí)返回-1. 請(qǐng)求連接請(qǐng)求連接 示例示例#include int socket_conn

36、ect(char *hostname, char *servport) int sockfd; struct sockaddr_in sockaddr; init_sockaddr( &sockaddr, hostname, servport ); sockfd = socket ( AF_INET, SOCK_STREAM, 0 ); if( connect ( sockfd,(struct sockaddr*)&sockaddr, sizeof(sockaddr) 0 ) exit(1); return sockfd; 接收連接接收連接接收連接是服務(wù)端的動(dòng)作接收連接是服務(wù)端

37、的動(dòng)作. .為了接收客戶端的連接請(qǐng)求為了接收客戶端的連接請(qǐng)求, ,服務(wù)程序在調(diào)用服務(wù)程序在調(diào)用bindbind進(jìn)行命名后進(jìn)行命名后, ,要執(zhí)行要執(zhí)行兩個(gè)步驟兩個(gè)步驟: :調(diào)用調(diào)用 listen listen 函數(shù)創(chuàng)建一個(gè)連接請(qǐng)求的偵聽(tīng)隊(duì)列函數(shù)創(chuàng)建一個(gè)連接請(qǐng)求的偵聽(tīng)隊(duì)列調(diào)用調(diào)用 accept accept 函數(shù)接收連接函數(shù)接收連接接收連接接收連接 創(chuàng)建連接隊(duì)列創(chuàng)建連接隊(duì)列為了創(chuàng)建一個(gè)連接隊(duì)列為了創(chuàng)建一個(gè)連接隊(duì)列, ,必須調(diào)用必須調(diào)用listenlisten函數(shù)函數(shù)#include int listen(int sockfd, int backlog );sockfd:是bind后的文件描述符.

38、backlog:設(shè)置請(qǐng)求排隊(duì)的最大長(zhǎng)度.當(dāng)有多個(gè)客戶端程序和服務(wù)端相連時(shí), 使用這個(gè)表示排隊(duì)長(zhǎng)度. listen函數(shù)將bind的文件描述符變?yōu)楸O(jiān)聽(tīng)套接字.返回的情況和bind一樣. 接收連接接收連接 接收客戶連接接收客戶連接ListenListen建立隊(duì)列后建立隊(duì)列后, ,可以調(diào)用可以調(diào)用acceptaccept來(lái)接收套接字上到達(dá)的連接請(qǐng)求來(lái)接收套接字上到達(dá)的連接請(qǐng)求#include int accept(int sockfd, struct sockaddr *clientaddr, socklen_t address_len );sockfd:是listen后的文件描述符. clienta

39、ddr,addresslen是用來(lái)給客戶端的程序填寫(xiě)的,服務(wù)器端只要傳遞指針就可以了. bind,listen和accept是服務(wù)器端用的函數(shù),accept調(diào)用時(shí),服務(wù)器端的程序會(huì)一直阻塞到有一個(gè) 客戶程序發(fā)出了連接. accept成功時(shí)返回最后的服務(wù)器端的文件描述符,這個(gè)時(shí)候服務(wù)器端可以向該描述符寫(xiě)信息了. 失敗時(shí)返回-1send send 和和 recvrecv套接字之間一旦建立了連接套接字之間一旦建立了連接, ,就可以開(kāi)始傳送數(shù)據(jù)就可以開(kāi)始傳送數(shù)據(jù). .我們可以使用標(biāo)準(zhǔn)我們可以使用標(biāo)準(zhǔn)讀寫(xiě)函數(shù)讀寫(xiě)函數(shù)readread和和writewrite對(duì)套接字進(jìn)行讀寫(xiě)對(duì)套接字進(jìn)行讀寫(xiě). .read(

40、socket, buffer, len) read(socket, buffer, len) 和和 write( socket, buffer, len)write( socket, buffer, len)套接字庫(kù)還提供套接字庫(kù)還提供sendsend和和recvrecv兩個(gè)函數(shù)進(jìn)行數(shù)據(jù)讀寫(xiě)兩個(gè)函數(shù)進(jìn)行數(shù)據(jù)讀寫(xiě), ,它們類似于它們類似于readread和和write,write,但只能用于套接字但只能用于套接字. .同時(shí)它們還具備標(biāo)準(zhǔn)同時(shí)它們還具備標(biāo)準(zhǔn)I/OI/O函數(shù)沒(méi)有的功能函數(shù)沒(méi)有的功能. .send send 和和 recvrecv#include int send( int sockf

41、d,void* buffer, size_t length, int flag );int recv( int sockfd, void* buffer, size_t length, int flag );sockfd:本地套接字描述符. buffer:保存有發(fā)送數(shù)據(jù)的緩沖區(qū)的指針,長(zhǎng)度有l(wèi)ength指定flags:. 傳輸控制方式(0,MSG_DONTROUTE/MSG_OOB/MSG_PEEK/MSG_WAITALL)流套接字操作示例流套接字操作示例: :客戶程序向服務(wù)程序請(qǐng)求得到日期和時(shí)間信息客戶程序向服務(wù)程序請(qǐng)求得到日期和時(shí)間信息/客戶端程序客戶端程序client.c ,將用到子函數(shù)

42、將用到子函數(shù)socket_connect#include void main() int sockfd, n; char recvbuffer128; sockfd = socket_connect ( “”, “13”); while( (n= recv(sockfd,recvbuffer, 127, 0) 0 ) recvbuffern = 0; printf(“%s”, recvbuffer); close( sockfd );流套接字操作示例流套接字操作示例: :客戶程序向服務(wù)程序請(qǐng)求得到日期和時(shí)間信息客戶程序向服務(wù)程序請(qǐng)求得到日期和時(shí)間信息/服務(wù)端程序服務(wù)端程

43、序server.c , 將用到子函數(shù)將用到子函數(shù)make_socket#include #define MAX_LISTEN 30void main() int listen_fd, connected_fd; char buffer128; time_t ticks; struct sockaddr_in client_addr; listen_fd = make_socket(13); listen( listen_fd, MAX_LISTEN );流套接字操作示例流套接字操作示例: :客戶程序向服務(wù)程序請(qǐng)求得到日期和時(shí)間信息客戶程序向服務(wù)程序請(qǐng)求得到日期和時(shí)間信息 for ( ; ; )

44、 connected_fd = accept ( listen_fd, (struct sockaddr*)client_addr, sizeof(client_addr); printf(“connect from %s, port %dn”, inet_ntoa(client_addr.sin_addr.s_addr), ntohs(client_addr.sin_port) ); ticks = time( NULL ); sprintf( buf, “the time is %srn”, ctime(&ticks); send( connected_fd, buf, strlen(buf), 0 ); close( connected_fd ); 通信模式通信模式 數(shù)據(jù)報(bào)套接字采用數(shù)據(jù)報(bào)套接字采用UDPUDP協(xié)議協(xié)議, , 是無(wú)連接是無(wú)連接, ,不可靠的不可靠的. . 客戶不與服務(wù)器建立連接客戶不與服務(wù)器建立連接, ,只是通過(guò)只是通過(guò)sendtosendto函數(shù)發(fā)送數(shù)據(jù)報(bào)函數(shù)發(fā)送數(shù)據(jù)報(bào). . 服務(wù)端也不

溫馨提示

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

最新文檔

評(píng)論

0/150

提交評(píng)論