版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1、第十三章 UNIX系統(tǒng)程序設(shè)計(jì)(二),系統(tǒng)調(diào)用返回值 (page 323),大多數(shù)的系統(tǒng)調(diào)用都返回一個(gè)值。如打開一個(gè)文件的系統(tǒng)調(diào)用fd=open(name,mode)返回一個(gè)文件描述符fd。 當(dāng)指定的文件不存在時(shí)返回 -1。返回值 -1指示一個(gè)系統(tǒng)調(diào)用可能失敗了,這時(shí)系統(tǒng)的全局變量errno值為相應(yīng)的出錯(cuò)代碼。 系統(tǒng)還定義了另外兩個(gè)外部變量,即對(duì)應(yīng)于出錯(cuò)代碼的消息數(shù)組sys_errlist和比該數(shù)組最大下標(biāo)大1的整型變量sys_neer。 為了在系統(tǒng)調(diào)用失敗后獲得出錯(cuò)代碼和出錯(cuò)信息,我們可以編寫一個(gè)如下的C函數(shù):,#include void syserr(syscall) char *sysc
2、all; extern int errno,sys_nerr; extern const char const *sys_errlist; fprintf(stderr,ERROR: %s %d,syscall,errno); if(errno0 ,13.1文件系統(tǒng)程序設(shè)計(jì),13.1.1獲取文件的狀態(tài) 在C語(yǔ)言程序設(shè)計(jì)中,有時(shí)需要獲得有關(guān)文件的類型、大小、文件主及時(shí)間信息,這可通過(guò)系統(tǒng)調(diào)用stat和fstat來(lái)獲取。 include include int stat(pathname,sbuf) char pathname; int fstat(fd,sbuf) int fd; struct
3、stat *sbuf; stat和fstat都是從一個(gè)文件的i節(jié)點(diǎn)獲得有關(guān)狀態(tài)信息的。stat是根據(jù)參數(shù)pathname給出的文件路徑名,通過(guò)搜索目錄項(xiàng)結(jié)構(gòu)來(lái)獲取文件的外存i節(jié)點(diǎn),fstat是根據(jù)參數(shù)fd給出的打開文件描述符,通過(guò)打開文件結(jié)構(gòu)獲取內(nèi)存i節(jié)點(diǎn)。,stat結(jié)構(gòu)定義如下:,struct stat dev_t st_dev; /* i節(jié)點(diǎn)所在設(shè)備號(hào)*/ ino_t st_ino; /* i節(jié)點(diǎn)號(hào)(ushort) */ ushort st_mode; /* 文件模式 */ short st_nlink; /* 文件鏈接數(shù)(short)*/ ushort st_uid; /* 文件主用戶標(biāo)
4、識(shí)符 */ ushort st_gid; /* 文件用戶組標(biāo)識(shí)符 */ dev_t st_rdev; /* 針對(duì)設(shè)備特別文件的設(shè)備號(hào)*/ off_t st_size; /* 文件的當(dāng)前大小,特別文件為0*/ time_t st_atime; /* 文件存取時(shí)間(long)*/ time_t st_mtime; /* 文件修改時(shí)間(long)*/ time_t st_ctime; /* 文件的創(chuàng)建時(shí)間*/ 用fstat可以通過(guò)打開的無(wú)名管道文件描述符,訪問(wèn)“隱藏”的i節(jié)點(diǎn),獲取其狀態(tài)信息,而stat調(diào)用則無(wú)能為力。,13.1.2搜索目錄樹,有時(shí),用戶需要在一棵目錄樹的范圍內(nèi)對(duì)文件和目錄執(zhí)行某些操
5、作。例行程序ftw能從指定的目錄開始掃描目錄樹,并對(duì)找到的每一個(gè)目錄項(xiàng),調(diào)用用戶定義的函數(shù)。ftw函數(shù)的格式如下: #include int ftw(path,func,depth) char *path; /* 指向目錄路徑名 */ int func(); /* 用戶定義的處理函數(shù) */ int depth; /* 即可同時(shí)打開的文件個(gè)數(shù) */,用戶定義的函數(shù)的格式:,int func(name,statptr,type) char *name; /* 存放ftw找到的目標(biāo)名 */ struct stat *statptr; /* 指向stat結(jié)構(gòu)指針, ftw在該結(jié)構(gòu)中存放目標(biāo)的狀態(tài)信息
6、*/ int type; /* ftw指示目標(biāo)的類型 和執(zhí)行狀態(tài)*/ /* body of function */ ,參數(shù)type的目標(biāo)類型,參數(shù)type的目標(biāo)類型在ftw.h中定義,類型取值為: FTW_F 目標(biāo)是文件 FTW_D 目標(biāo)是目錄 FTW_DNR 目標(biāo)是不能讀的目錄 FTW_NS 目標(biāo)不能被stat成功地執(zhí)行 如果目標(biāo)是不能讀的目錄,那么此目錄的所有下級(jí)也不能處理。對(duì)于stat不能成功執(zhí)行的目標(biāo),那么傳送給用戶的stat結(jié)構(gòu)中的內(nèi)容是無(wú)效的。 在調(diào)用ftw中,如用戶定義的函數(shù)返回非0值,ftw就中止掃描,并把此時(shí)用戶函數(shù)的返回值作為ftw的返回值。如ftw在執(zhí)行中出錯(cuò),會(huì)使ftw
7、返回 -1,同時(shí)在errno中設(shè)置出錯(cuò)代碼。,下面的程序使用ftw及dspstatus函數(shù)輸出一棵目錄樹中所有帶有路徑的目錄或文件名,對(duì)于文件還顯示文件的類型、i節(jié)點(diǎn)號(hào)及文件鏈接數(shù),對(duì)于特別文件還顯示主次設(shè)備號(hào)。用戶也可以在自定義函數(shù)中執(zhí)行其他類型的操作。 主程序從參數(shù)中獲得一個(gè)作為目錄樹掃描起點(diǎn)的路徑名,該參數(shù)的缺省值為當(dāng)前目錄。,#incude #incude #incude int dspstatus(name,statptr,type) char *name; struct stat *statptr; int type; switch(type) case FTW_DNR: prin
8、tf(-30st: Dir cant readn,name); case FTW_NS:/* 執(zhí)行失敗 */ return(0); default:/* 正常狀態(tài) */ break; printf(-30st:,name);,switch(statprt-st_mode .,main(argc,argv) int argc; char *argv; int dspstatus(); if(argc2) ftw(.,dspstatus,2); else ftw(argv1,dspstatus,2); exit(0); ,13.2用文件的系統(tǒng)調(diào)用實(shí)現(xiàn)進(jìn)程通信,13.2.1利用文件的系統(tǒng)調(diào)用實(shí)現(xiàn)信號(hào)
9、燈 可以用creat系統(tǒng)調(diào)用生成一個(gè)新文件,但如該文件原已存在,則調(diào)用進(jìn)程要對(duì)其有寫權(quán)限才能將該文件的長(zhǎng)度截為零。利用這一特性可以將一個(gè)預(yù)先約定好的文件作為信號(hào)燈。 當(dāng)若干進(jìn)程要訪問(wèn)臨界資源時(shí),規(guī)定遵循以下協(xié)議:先試圖創(chuàng)建同一個(gè)沒(méi)有寫權(quán)限的文件,這樣只有一個(gè)進(jìn)程才能獲得成功,允許其進(jìn)入臨界區(qū),其他進(jìn)程的creat操作將失?。ǚ祷刂禐?1)。 進(jìn)程從臨界區(qū)退出時(shí)就刪除這個(gè)作為信號(hào)燈的文件,這樣正在等待中的進(jìn)程的一個(gè)就能成功地創(chuàng)建它。,13.2.2利用管道實(shí)現(xiàn)進(jìn)程間通信,用C語(yǔ)言實(shí)現(xiàn)含有管道符的UNIX復(fù)合命令 who | wc l,父進(jìn)程,子進(jìn)程1,子進(jìn)程2,圖象改換,圖象改換,who_wc()
10、 /* who | wc */ int pfd2; if(pipe(pfd)=-1) syserr(pipe); switch(fork() case -1: syserr(fork); case 0:/* 子進(jìn)程1 */ if(close(1)=-1) syserr(close); if(dup(pfd1)!=1) fprintf(stderr,ERROR: dupn); exit(1); ,if(close(pfd0)=-1|close(pfd1)=-1) syserr(close2); execlp(who,who,NULL); switch(fork() case 0:/*子進(jìn)程2 *
11、/ if(close(0)=-1) syserr(close3); if(dup(pfd0)!=0) fprintf(stderr,ERROR: dup2n); if(close(pfd0)=-1|close(pfd1)=-1) syserr(close4); execlp(wc,wc,-l,NULL); syserr(execlp2); if(close(pfd0)=-1|close(pfd1)=-1) syserr(“close5”); /* 父進(jìn)程 */ while(wait(NULL)!=-1) ; ,系統(tǒng)調(diào)用int dup(int fd)復(fù)制一個(gè)已存在的文件標(biāo)識(shí)字,返回同一個(gè)文件或管
12、道的新的文件標(biāo)識(shí)字,該文件標(biāo)識(shí)字是當(dāng)前可用的最小文件標(biāo)識(shí)字。兩個(gè)文件標(biāo)識(shí)字共享一個(gè)文件讀寫指針。 利用dup系統(tǒng)調(diào)用使用編號(hào)最小的可用文件標(biāo)識(shí)字的規(guī)則,可以使對(duì)任何文件或管道的讀寫與所希望的文件標(biāo)識(shí)字聯(lián)系起來(lái),如使用fd為0的標(biāo)準(zhǔn)輸入與管道讀相聯(lián)系,fd為1的標(biāo)準(zhǔn)輸出與管道寫相聯(lián)系,這就是管道命令的運(yùn)行機(jī)制。 如將文件的輸入/輸出與標(biāo)準(zhǔn)輸入/輸出相聯(lián)系,這就是I/O重定向的運(yùn)行機(jī)制。,為了將前一個(gè)命令的標(biāo)準(zhǔn)輸出與一個(gè)管道的寫端相連接,后一個(gè)命令的標(biāo)準(zhǔn)輸入與同一個(gè)管道的讀端相連接,可以先關(guān)閉文字標(biāo)識(shí)字0且用dup復(fù)制讀管道的文件標(biāo)識(shí)字,由于0是最小的文件標(biāo)識(shí)字,且又剛剛使它處于“空閑”可用的狀態(tài)
13、,故dup將返回標(biāo)識(shí)字為0的管道的讀端。 同樣也可使標(biāo)識(shí)字1成為管道的寫端。 接下來(lái)如果再關(guān)閉管道文件的原先兩個(gè)文件標(biāo)識(shí)字,就構(gòu)成標(biāo)識(shí)字為0和1的管道的讀寫端。 由于子進(jìn)程和通過(guò)exec命令執(zhí)行的進(jìn)程繼承了父進(jìn)程的所有文件標(biāo)識(shí)字和打開文件結(jié)構(gòu),故用這種方法可以建立管道命令符左右兩邊的命令輸出和輸入的聯(lián)系。,父進(jìn)程首先生成一個(gè)管道文件,再產(chǎn)生第一個(gè)子進(jìn)程。 子進(jìn)程繼承了父進(jìn)程的標(biāo)準(zhǔn)文件標(biāo)識(shí)字和管道文件標(biāo)識(shí)字,接著關(guān)閉標(biāo)準(zhǔn)輸出,復(fù)制寫管道文件標(biāo)識(shí)字,其值為1。然后子進(jìn)程關(guān)閉了從父進(jìn)程繼承來(lái)的管道文件的原兩個(gè)標(biāo)識(shí)字,使得該管道文件的寫端僅與子進(jìn)程的標(biāo)準(zhǔn)輸出相連接。接下來(lái)子進(jìn)程改換圖像,執(zhí)行UNIX命
14、令who。 在who命令的執(zhí)行期間,繼承了第一個(gè)子進(jìn)程的全部文件標(biāo)識(shí)字和打開文件及管道文件狀態(tài),who命令的標(biāo)準(zhǔn)輸出就源源不斷地寫入管道文件中。 為了建立第二個(gè)命令的管道讀端,原父進(jìn)程又產(chǎn)生了第二個(gè)子進(jìn)程,類似地,將標(biāo)準(zhǔn)輸入與管道文件的讀端相連接,并執(zhí)行UNIX命令wc,使該命令從管道的讀端接收數(shù)據(jù),從而建立了who和wc兩個(gè)命令的讀寫聯(lián)系。,13.4遠(yuǎn)程進(jìn)程間通信,利用管道通信的進(jìn)程必須屬于同一進(jìn)程族,消息通信、共享內(nèi)存和信號(hào)燈只能用于同一臺(tái)機(jī)器上的進(jìn)程間通信,它們都不能用于分布在網(wǎng)絡(luò)上的進(jìn)程間通信。UNIX提供了Socket(插座或稱套接字)的通信機(jī)構(gòu),主要用于異地進(jìn)程間的通信,也可用于本
15、地進(jìn)程間通信。 Socket是在傳送層上提供給應(yīng)用程序的網(wǎng)絡(luò)通信接口。Socket通過(guò)“域”來(lái)劃分所支持的協(xié)議,不同的通信域間不能建立通信連接。目前最常用的是支持TCP/IP協(xié)議的INET通信域和支持UNIX系統(tǒng)中進(jìn)程通信的UNIX通信域。,13.4.1 Socket通信概述,通信域,通信域在sys/socket.h中定義: #define AF_UNIX 1 /* 用于UNIX內(nèi)部 */ #define AF_INET 2 /* 支持UDP,TCP等 */ 每種通信域又有幾種類型方式,它們也在sys/socket.h中定義: #define SOCK_STREAM 1 /* 虛電路方式*/
16、#define SOCK_DGRAM 2 /* 數(shù)據(jù)報(bào)方式 */ Socket模仿UNIX文件操作來(lái)實(shí)現(xiàn)進(jìn)程通信操作,將網(wǎng)絡(luò)通信看成網(wǎng)絡(luò)上兩端進(jìn)程間的I/O操作。因此定義了類似文件描述符的Socket描述符,以及與文件讀寫相似的數(shù)據(jù)接收和發(fā)送操作。,Socket通信模型,由于建立打開文件結(jié)構(gòu),取得文件描述符是建立進(jìn)程與本地文件靜態(tài)資源之間的聯(lián)系,而建立網(wǎng)絡(luò)的連接需要指定協(xié)議,經(jīng)過(guò)多次的握手(請(qǐng)求、應(yīng)答)過(guò)程,故網(wǎng)絡(luò)上的進(jìn)程通信要比文件I/O考慮更多的情況。 Socket通信采用了顧客服務(wù)員模型,建立連接時(shí),顧客進(jìn)程與服務(wù)員進(jìn)程所做的工作是不對(duì)稱的。圖13-2給出了Socket實(shí)現(xiàn)面向連接的進(jìn)程
17、通信基本過(guò)程。,1建立插座,sockfd=socket(domain,type,protocal) int sockfd; 插座標(biāo)識(shí)字 int domain,type,protocal; 通信域,通信方式、 協(xié)議 domain指定通信域,取值主要有AF_UNIX,AF_INET。 type指明通信方式,主要取值有SOCK_STREAM,SOCK_DGRAM。 protocal規(guī)定了通信協(xié)議,一般可選擇0,表示將遵循通信域和插座類型使用的通信協(xié)議。當(dāng)使用INET通信域的數(shù)據(jù)報(bào)方式時(shí),protocal取值為IPPROTO_UDP。 當(dāng)調(diào)用成功,socket返回一個(gè)類似于文件描述符的socket描述
18、符號(hào),可為后繼的其他的調(diào)用使用。,2聯(lián)系socket地址名和socket描述符,int bind(sockfd,myaddr,addrlen) int sockfd,addrlen /* socket描述字,myaddr的地址長(zhǎng)度 */ const struct sockaddr *myaddr; /* 名字(UNIX)或地址(互連網(wǎng)域)*/ 對(duì)INET通信域,參數(shù)myaddr是一個(gè)在netinet/in.h中定義的結(jié)構(gòu)sockaddr_in: struct sockaddr_in short sin_family;/* 通信域值為AF_INET */ u_short sin_port; /*
19、 16位端口號(hào) */ struck in_addr sin_addr;/* 32位IP地址 */ ;,3啟動(dòng)一個(gè)連接請(qǐng)求(client),int connect (sockfd, servaddr, addrlen) int sockfd,addrlen; struct sockaddr *servaddr; servaddr是通信信道另一個(gè)端點(diǎn)上的進(jìn)程地址,addrlen是地址長(zhǎng)度。 sockaddr用于socket與TCP/IP協(xié)議模塊交換地址參數(shù),該結(jié)構(gòu)對(duì)大多數(shù)基于socket的應(yīng)用程序是透明的,其定義如下: struct sockaddr u_short sa_family; /* 地
20、址類型 */ char sa_data14 /* 14字節(jié)地址 */ ;,4接受連接請(qǐng)求(server),int listen(sockfd,queuelen) listen調(diào)用為指定的插座規(guī)定能接受的連接請(qǐng)求的最大數(shù)目,也即隊(duì)列的最大長(zhǎng)度。 newsockfd=accept(sockfd,clieaddr,addrlen) struct sockaddr *clieaddr; 取隊(duì)列中第一個(gè)連接請(qǐng)求,clieaddr和addrlen是accept返回時(shí)由系統(tǒng)填入的對(duì)方插座地址和地址結(jié)構(gòu)的長(zhǎng)度。 返回值newsockfd是一個(gè)與sockfd不同的新的插座描述符,這樣服務(wù)器一方面可以在與sock
21、fd相關(guān)的地址上繼續(xù)監(jiān)聽對(duì)方新的服務(wù)請(qǐng)求,另一方面可以在與newsockfd相關(guān)的另一個(gè)信道上與請(qǐng)求連接的client進(jìn)程進(jìn)行聯(lián)系通信。,5數(shù)據(jù)傳送,count=send(sockfd,msg,len,flags) count=write(sockfd,msg,len) count=recv(sockfd,buf,len,flags) count=read(sockfd,buf,len) msg為發(fā)送數(shù)據(jù)的緩沖區(qū), buf是接收數(shù)據(jù)的緩沖區(qū), flags為0時(shí),表示正常的數(shù)據(jù)發(fā)送或接收,flags等于MSG_OOB時(shí)表示發(fā)送或接收帶外數(shù)據(jù)(緊急數(shù)據(jù));flags等于MSG_PEEK時(shí)表示可以“
22、偷看”一個(gè)到來(lái)的報(bào)文,檢查其內(nèi)容,但不把它從隊(duì)列中移去。當(dāng)flags等于MSG_DONTROUTE時(shí)表示可以在沒(méi)有網(wǎng)絡(luò)路由選擇的情況下發(fā)送數(shù)據(jù)。 返回值count是實(shí)際發(fā)送或接收的數(shù)據(jù)長(zhǎng)度。,6關(guān)閉插座,可以像關(guān)閉打開的文件一樣,利用close系統(tǒng)調(diào)用可關(guān)閉一插座,釋放插座描述符。 int close(int sockfd) 插座關(guān)閉后,在連接狀態(tài)下正在進(jìn)行的信息發(fā)送還能繼續(xù)進(jìn)行。,13.4.3 socket通信程序設(shè)計(jì),一個(gè)使用TCP/IP協(xié)議進(jìn)行socket通信的例子。 服務(wù)器方使用getsockname獲得一未用端口號(hào),并將其打印出來(lái),以供client程序使用該端口號(hào)作為命令參數(shù),與服務(wù)
23、器建立socket連接。此端口號(hào)也可由用戶直接定義。 服務(wù)器進(jìn)程在調(diào)用accept獲得顧客方發(fā)來(lái)的連接請(qǐng)求后,產(chǎn)生子進(jìn)程,使子進(jìn)程使用一個(gè)新的插座描述符與顧客程序通信,而父進(jìn)程繼續(xù)在原地址上監(jiān)聽。,通信雙方程序的頭文件,/* sockcom.h */ #include #include #include #include #include ,/* server */ #include “sockcom.h” main() int sockfd,newsockfd,length,count; struct sockaddr_in server; char buf1024; sockfd=sock
24、et(AF_INET,SOCK_STREAM,0); 生成插座 server.sin_family=AF_INET; /* 構(gòu)成socked名(地址) 和建立聯(lián)系 */ server.sin_addr.s_addr=INADDR_ANY; server.sin_port=0; /* 選擇一個(gè)已釋放的端口號(hào) */ if(bind(sockfd,(struct sockaddr *) /* 獲取并打印端口號(hào) */,/* 獲取并打印端口號(hào) */ length=sizeof(server); if(getsockname(sockfd,(strcut sockaddr *) ,while(1) new
25、sockfd=accept(sockfd,(struct sockaddr *)0 ,(int *)0); if(!fork() 子進(jìn)程 close(sockfd); bzero(buf,sizeof(buf); 調(diào)用庫(kù)函數(shù),清緩沖區(qū) if(count=recv(newsockfd,buf,sizeof(buf),0)0) syserr(“Reading stream message”); printf(“message received: %sn”,buf); exit(0); close(newsockfd); ,調(diào)用形式:命令,主機(jī)名,端口號(hào),/* client */ #include
26、“sockcom.h” main(argc,argv) int argc; char *argv; int sockfd; struct sockaddr_in server; struct hostent *hp,*gethostbyname(); char msg1024;,sockfd=socket(AF_INET,SOCK_STREAM,0); /* 與由命令行參數(shù)指定的主機(jī)建立連接 */ hp=gethostbyname(argv1)=NULL) server.sin_family = AF_INET; bcopy(char *)hp-h_addr,(char *) ,while(1
27、) printf(“Enter send message: ”); scanf(“%s”,msg); if(!strlen(msg) break; if(send(sockfd,msg,strlen(msg),0)0) syserr(“sendint message”); bzero(msg,sizeof(msg); printf(“EOF.disconnectn”); close(sockfd); exit(0); ,在顧客方程序中調(diào)用了gethostbyname,通過(guò)查找/etc/hosts文件,將服務(wù)器主機(jī)的IP地址填入hostent結(jié)構(gòu)中,并返回指向該結(jié)構(gòu)的指針。hostnet在net
28、db.h中定義: struct hostent char *h_name; /* 主機(jī)名 */ char *h_aliases; /* 別名表 */ int h_addrtype; /* 主機(jī)地址類型 */ int h_length; /* 地址長(zhǎng)度 */ char *h_addr_list; /* 域名服務(wù)器地址表,以NULL終止 */ ; bcopy()是字節(jié)拷貝函數(shù)。,socket進(jìn)階,1套接字(插座)的功能 套接字實(shí)質(zhì)上提供了進(jìn)程通信的端點(diǎn)。進(jìn)程通信之前,雙方首先必須各自創(chuàng)建一個(gè)端點(diǎn),否則是沒(méi)有辦法建立聯(lián)系并相互通信的。正如打電話之前,雙方必須各自擁有一臺(tái)電話機(jī)一樣。 有人說(shuō):“在UN
29、IX系統(tǒng)中,任何東西都是一個(gè)文件?!边@句話描述了這樣一個(gè)事實(shí):在UNIX系統(tǒng)中,任何對(duì)I/O的操作,都是通過(guò)讀或?qū)懸粋€(gè)文件描述符來(lái)實(shí)現(xiàn)的。所以,如果你想通過(guò)Internet和另外一個(gè)程序通信的話,你將會(huì)是通過(guò)一個(gè)文件的描述符來(lái)實(shí)現(xiàn)的。 可以用write( )和read( )對(duì)套接字描述符進(jìn)行操作的,但是,通過(guò)使用send( )和recv( )函數(shù),你可以對(duì)網(wǎng)絡(luò)數(shù)據(jù)的傳輸進(jìn)行更好的控制。,2Socket是怎樣在網(wǎng)絡(luò)上傳輸數(shù)據(jù)的,OSI模型共分為七層。從下到上依次為:物理層、數(shù)據(jù)鏈路層、網(wǎng)絡(luò)層、運(yùn)輸層、會(huì)話層、表示層和應(yīng)用層。這個(gè)模型是最一般的模型,但是在UNIX中,真正用到的模型層次是下面這樣子
30、的: 應(yīng)用層(Telnet、FTP等等) 主機(jī)間對(duì)話層,即傳輸層(TCP和UDP) 網(wǎng)絡(luò)層(IP和路由) 網(wǎng)絡(luò)底層(相當(dāng)于OSI模型中網(wǎng)絡(luò)、數(shù)據(jù)鏈路和物理層) 對(duì)流式套接字我們所需要做的是調(diào)用send( )函數(shù)來(lái)發(fā)送數(shù)據(jù)。UNIX系統(tǒng)內(nèi)核中已經(jīng)建立了Transport Layer和Internet Layer。硬件負(fù)責(zé)NetworkAccess Layer。,3基本轉(zhuǎn)換函數(shù),(1)網(wǎng)絡(luò)字節(jié)順序 因?yàn)槊恳粋€(gè)機(jī)器內(nèi)部對(duì)變量的字節(jié)存儲(chǔ)順序不同(有的系統(tǒng)是高位在前,低位在后,而有的系統(tǒng)是低位在前,高位在后),而網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù)順序是一定要統(tǒng)一的。所以對(duì)與內(nèi)部字節(jié)表示順序和網(wǎng)絡(luò)字節(jié)順序不同的機(jī)器,一定要對(duì)
31、數(shù)據(jù)進(jìn)行轉(zhuǎn)換(比如IP地址的表示,端口號(hào)表示)。 內(nèi)部字節(jié)順序和網(wǎng)絡(luò)字節(jié)順序相同的機(jī)器也要調(diào)用轉(zhuǎn)換函數(shù),但是真正轉(zhuǎn)換還是不轉(zhuǎn)換是由系統(tǒng)函數(shù)自己來(lái)決定的。,(2) 有關(guān)的轉(zhuǎn)換函數(shù),通常使用的有兩種數(shù)據(jù)類型:短型(兩個(gè)字節(jié))和長(zhǎng)型(四個(gè)字節(jié))。下面介紹的這些轉(zhuǎn)換函數(shù)對(duì)于這兩種的無(wú)符號(hào)整型變量都可以進(jìn)行正確的轉(zhuǎn)換。 如果你想將一個(gè)短型數(shù)據(jù)從主機(jī)字節(jié)順序轉(zhuǎn)換到網(wǎng)絡(luò)字節(jié)順序,有這樣一個(gè)函數(shù):它以“h”開頭,代表“主機(jī)”;緊跟著它的是“to”,代表“轉(zhuǎn)換到”;然后是“n”,代表“網(wǎng)絡(luò)”;最后是“s”,代表“短型數(shù)據(jù)”。h-to-n-s,就是htons( )函數(shù)。,套接字字節(jié)轉(zhuǎn)換函數(shù)列表:,htons( )
32、主機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序(對(duì)無(wú)符號(hào)短型進(jìn)行操作) htonl( )主機(jī)字節(jié)順序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)順序(對(duì)無(wú)符號(hào)長(zhǎng)型進(jìn)行操作) ntohs( )網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序(對(duì)無(wú)符號(hào)短型進(jìn)行操作) ntohl( )網(wǎng)絡(luò)字節(jié)順序轉(zhuǎn)換為主機(jī)字節(jié)順序(對(duì)無(wú)符號(hào)長(zhǎng)型進(jìn)行操作),在struct socketaddr_in 中的sin_addr和sin_port的字節(jié)順序都是網(wǎng)絡(luò)字節(jié)順序,而sin_family卻不是網(wǎng)絡(luò)字節(jié)順序。這是因?yàn)閟in_addr和sin_port是從IP和UDP協(xié)議層取出數(shù)據(jù)的,而在IP和UDP協(xié)議層,是直接和網(wǎng)絡(luò)相關(guān)的,所以它們必須使用網(wǎng)絡(luò)字節(jié)順序。 sin_family域只
33、是內(nèi)核用來(lái)判斷struct socketaddr_in存儲(chǔ)的是什么類型的數(shù)據(jù),并且,sin_family永遠(yuǎn)也不會(huì)被發(fā)送到網(wǎng)絡(luò)上,所以可以使用主機(jī)字節(jié)順序來(lái)存儲(chǔ)。,(3) IP地址轉(zhuǎn)換,UNIX系統(tǒng)提供很多用于轉(zhuǎn)換IP地址的函數(shù)。假設(shè)有一個(gè)struct sockaddr_in ina,并且IP是2,如果想把它存儲(chǔ)到ina中,可以使用函數(shù)inet_addr( ),它能夠把一個(gè)用數(shù)字和點(diǎn)表示的IP地址的字符串轉(zhuǎn)換成一個(gè)無(wú)符號(hào)長(zhǎng)整型。使用方式為: ina.sin_addr.s_addr=inet_addr(2); inet_addr( )返回的地址已經(jīng)
34、是網(wǎng)絡(luò)字節(jié)順序了,沒(méi)有必要再去調(diào)用htonl( )函數(shù)。 必須注意,如果inet_addr( )函數(shù)執(zhí)行錯(cuò)誤,它將會(huì)返回-1,二進(jìn)制的無(wú)符號(hào)整數(shù)值-1,相當(dāng)于55,一個(gè)廣播用的IP地址。,如果有一個(gè)struct in_addr,并且想把它代表的地址打印出來(lái)(按照數(shù)字.數(shù)字.數(shù)字.數(shù)字的格式),可以使用函數(shù)inet_ntoa( ),例如: printf(%s,inet_ntoa(ina.sin_addr); 這段代碼將會(huì)把struct in_addr里面存儲(chǔ)的網(wǎng)絡(luò)地址以數(shù)字.數(shù)字.數(shù)字.數(shù)字的格式顯示出來(lái)。,inet_ntoa( )返回一個(gè)字符指針,它指向一個(gè)定義在函數(shù)inet_ntoa( )中的static類型字符串。所以每次調(diào)用inet_ntoa( ),都會(huì)改變最后一次調(diào)用inet_ntoa( )函數(shù)時(shí)所得到的結(jié)果。例如: char *a1, *a2; a1=inet
溫馨提示
- 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ì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 乘客關(guān)系與服務(wù)投訴處理考核試卷
- 大學(xué)生創(chuàng)業(yè)教育與孵化器建設(shè)考核試卷
- 乳品市場(chǎng)營(yíng)銷策略創(chuàng)新考核試卷
- 地震知識(shí)與應(yīng)用考核試卷
- 創(chuàng)業(yè)者創(chuàng)業(yè)經(jīng)驗(yàn)總結(jié)與分享考核試卷
- 太陽(yáng)能熱水器設(shè)計(jì)與制造考核試卷
- 2025-2030全球辛夷鼻炎丸行業(yè)調(diào)研及趨勢(shì)分析報(bào)告
- 智能信息處理課程設(shè)計(jì)
- 項(xiàng)目管理的課課程設(shè)計(jì)
- 注冊(cè)功能 課程設(shè)計(jì)
- 不銹鋼伸縮縫安裝施工合同
- 水土保持監(jiān)理總結(jié)報(bào)告
- Android移動(dòng)開發(fā)基礎(chǔ)案例教程(第2版)完整全套教學(xué)課件
- 醫(yī)保DRGDIP付費(fèi)基礎(chǔ)知識(shí)醫(yī)院內(nèi)培訓(xùn)課件
- 專題12 工藝流程綜合題- 三年(2022-2024)高考化學(xué)真題分類匯編(全國(guó)版)
- DB32T-經(jīng)成人中心靜脈通路裝置采血技術(shù)規(guī)范
- 【高空拋物侵權(quán)責(zé)任規(guī)定存在的問(wèn)題及優(yōu)化建議7100字(論文)】
- TDALN 033-2024 學(xué)生飲用奶安全規(guī)范入校管理標(biāo)準(zhǔn)
- 物流無(wú)人機(jī)垂直起降場(chǎng)選址與建設(shè)規(guī)范
- 冷庫(kù)存儲(chǔ)合同協(xié)議書范本
- AQ/T 4131-2023 煙花爆竹重大危險(xiǎn)源辨識(shí)(正式版)
評(píng)論
0/150
提交評(píng)論