第9章 嵌入式web服務(wù)器設(shè)計(jì)_第1頁
第9章 嵌入式web服務(wù)器設(shè)計(jì)_第2頁
第9章 嵌入式web服務(wù)器設(shè)計(jì)_第3頁
第9章 嵌入式web服務(wù)器設(shè)計(jì)_第4頁
第9章 嵌入式web服務(wù)器設(shè)計(jì)_第5頁
已閱讀5頁,還剩94頁未讀, 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1、 第9章 嵌入式web服務(wù)器設(shè)計(jì) 目的要求:了解HTTP協(xié)議。理解socket編程原理。掌握嵌入式Web服務(wù)器系統(tǒng)結(jié)構(gòu);嵌入式應(yīng)用接口技術(shù)。 重點(diǎn)難點(diǎn):掌握嵌入式Web服務(wù)器系統(tǒng)結(jié)構(gòu)網(wǎng)絡(luò)編程簡介 互聯(lián)網(wǎng)的歷史和發(fā)展 ISO/OSI七層協(xié)議 TCP/IP協(xié)議 Bekeley Socket庫-基于BSD Socket 1.1互聯(lián)網(wǎng)的歷史和發(fā)展 1971年,ARPANET,使用NCP協(xié)議(Network Control Program) 1973年,放棄NCP協(xié)議,研究新協(xié)議 1974年,發(fā)布TCP/IP協(xié)議和網(wǎng)關(guān)結(jié)構(gòu) 1981年,TCP/IP version 4標(biāo)準(zhǔn)確定ISO/OSI七層協(xié)議模型T

2、CP/IP協(xié)議族 TCP(Transmission Control Protocol) 傳輸控制協(xié)議,基于連接的服務(wù) UDP(User Datagram Protocol) 用戶數(shù)據(jù)報(bào)協(xié)議,無連接的服務(wù) IP(Internet Protocol) Internet協(xié)議,信息傳遞機(jī)制OSI模型與TCP/IP協(xié)議的對(duì)比TCP或UDPIP和路由網(wǎng)卡驅(qū)動(dòng)TelnetFTPWWW等消息傳遞流消息包的逐層遞增應(yīng)用Socket函數(shù)實(shí)現(xiàn)網(wǎng)絡(luò)功能一些Socket編程的概念 流(Stream) 連接(Connection) 阻塞(Block)、非阻塞(Non-block) 同步(Synchronous)、異步(a

3、synchronous) IP地址 字節(jié)順序IP地址 IP地址是Internet中唯一的地址標(biāo)識(shí), IP地址是一個(gè)32位長(正在擴(kuò)充到128位) 每個(gè)Internet包必須帶有IP地址 點(diǎn)分十進(jìn)制表示法 將IP地址的4個(gè)字節(jié)的數(shù)字用十進(jìn)制表示并用點(diǎn)隔開,如:00(0 xCA703AC8) IP地址的分級(jí) 子網(wǎng)掩碼(Subnet Mask)四級(jí)IP地址子網(wǎng)掩碼 也用點(diǎn)分十進(jìn)制表示 例如: 指明子網(wǎng)(局域網(wǎng))的范圍 Mask與IP地址進(jìn)行與操作即可得出子網(wǎng)范圍 例如 IP地址:與5子網(wǎng)掩碼:255.2

4、55.254.0即可得出這兩個(gè)IP地址處于同一個(gè)子網(wǎng)內(nèi)MAC地址 MAC地址是Ethernet協(xié)議使用的唯一地址 MAC地址是Ethernet NIC上自帶的,48位長。如:00-88-CC-06-05-43 MAC地址作用范圍是Ethernet(局域網(wǎng))內(nèi) MAC地址存在于每一個(gè)Ethernet包中,是Ethernet包頭的組成部分,Ethernet交換機(jī)根據(jù)Ethernet包頭中的MAC源地址和MAC目的地址實(shí)現(xiàn)包的交換和傳遞 MAC地址與IP地址無關(guān)字節(jié)順序 網(wǎng)絡(luò)字節(jié)順序(NBO,Network Byte Order) 使用統(tǒng)一的字節(jié)順序,避免兼容性問題 主機(jī)字節(jié)順序(HBO,Host

5、Byte Order) 不同的機(jī)器HBO不相同,與CPU設(shè)計(jì)有關(guān) Motorola 68k系列,HBO與NBO相同 Intel x86系列,HBO與NBO相反 Socket函數(shù)介紹需要用到的頭文件 數(shù)據(jù)類型:#include 函數(shù)定義:#include Berkeley Socket 常用函數(shù)列表 網(wǎng)絡(luò)連接函數(shù) 獲取/設(shè)置socket的參數(shù)或信息 轉(zhuǎn)換函數(shù)網(wǎng)絡(luò)連接函數(shù) socket bind connect listen accept select recv, recvfrom send, sendto close, shutdown獲取/設(shè)置socket的參數(shù)或信息 gethostbyadd

6、r, gethostbyname gethostname getpeername getprotobyname, getprotobynumber getservbyname, getservbyport getsockname getsockopt, setsockopt ioctl轉(zhuǎn)換函數(shù) IP地址轉(zhuǎn)換 inet_addr() inet_ntoa() 字節(jié)順序轉(zhuǎn)換 htons()-Host to Network Short htonl()-Host to Network Long ntohs()-Network to Host Short ntohl()-Network to Host L

7、ong數(shù)據(jù)結(jié)構(gòu):sockaddrstruct sockaddr unsigned short sa_family; /* address family, AF_xxx */char sa_data 14; /* 14 bytes of protocol address */;此數(shù)據(jù)結(jié)構(gòu)用做bind、connect、recvfrom、sendto等函數(shù)的參數(shù),指明地址信息數(shù)據(jù)結(jié)構(gòu):sockaddr_instruct sockaddr_in short int sin_family; /* Address family */unsigned short int sin_port; /* Port

8、number */struct in_addr sin_addr; /* Internet address */unsigned char sin_zero 8; /* Same size as structsockaddr */;該結(jié)構(gòu)與sockaddr兼容,供用戶填入?yún)?shù)數(shù)據(jù)結(jié)構(gòu):in_addrstruct in_addr unsigned long s_addr;這個(gè)數(shù)據(jù)結(jié)構(gòu)是由于歷史原因保留下來的,主要用作與以前的格式兼容。程序中實(shí)際只填寫sockaddr_in結(jié)構(gòu)struct sockaddr_in my_addr;my_addr.sin_family = AF_INET; my_a

9、ddr.sin_port = htons(3490); /* short, NBO*/my_addr.sin_addr.s_addr = inet_addr(0);bzero(&(my_addr.sin_zero), 8); 注意:sin_addr.s_addr填本機(jī)IP,如果此項(xiàng)填I(lǐng)NADDR_ANY 時(shí),表示自動(dòng)取本機(jī)IP填入該項(xiàng)(僅用于Server)函數(shù)簡介:socket Socket描述符與Linux中的文件描述符類似,也是一個(gè)int型的變量 函數(shù)調(diào)用:int socket(int domain, int type, int protocol);函數(shù)返回S

10、ocket描述符,返回-1表示出錯(cuò)domain參數(shù)只能取AF_INET, protocol參數(shù)一般取0 應(yīng)用示例:TCP:sockfd = socket(AF_INET,SOCK_STREAM,0);UDP:sockfd =socket(AF_INET, SOCK_DGRAM,0);函數(shù)簡介:bind 作為Server程序,需要與一個(gè)端口綁定int bind(int sockfd, struct sockaddr *my_addr, int addrlen);bind函數(shù)返回-1表示出錯(cuò),最常見的錯(cuò)誤是該端口已經(jīng)被其他程序綁定。 需要注意的一點(diǎn):在Linux系統(tǒng)中,1024以下的 端口只有擁有

11、root權(quán)限的程序才能綁定函數(shù)簡介:connect 連接某個(gè)Serverint connect(int sockfd, struct sockaddr *servaddr, int addrlen); servaddr是事先填寫好的結(jié)構(gòu),Server的IP和端口都在該數(shù)據(jù)結(jié)構(gòu)中指定。函數(shù)簡介:listen 開始監(jiān)聽已經(jīng)綁定的端口 需要在此前調(diào)用bind()函數(shù),否則由系統(tǒng)指定一個(gè)隨機(jī)的端口 int listen(int sockfd, int queue_length); 接收隊(duì)列 一個(gè)新的Client的連接請(qǐng)求先被放在接收隊(duì)列中,等待Server程序調(diào)用accept函數(shù)接受連接請(qǐng)求 queu

12、e_length指的就是接收隊(duì)列的長度 也就是在Server程序調(diào)用accept函數(shù)之前最大允許的連接請(qǐng)求數(shù),多余的連接請(qǐng)求將被拒絕函數(shù)簡介:accept accept()函數(shù)將響應(yīng)連接請(qǐng)求,建立連接 產(chǎn)生一個(gè)新的socket描述符來描述該連接 這個(gè)連接用來與特定的Client交換信息 int accept(int sockfd,struct sockaddr *addr,int *addrlen); addr將在函數(shù)調(diào)用后被填入連接對(duì)方的地址信息,如對(duì)方的IP、端口等。 accept缺省是阻塞函數(shù),阻塞直到有連接請(qǐng)求accept()函數(shù)應(yīng)用示例struct sockaddr_in their

13、_addr; /* 用于存儲(chǔ)連接對(duì)方的地址信息*/int sin_size = sizeof(struct sockaddr_in); (依次調(diào)用socket(), bind(), listen()等函數(shù))new_fd = accept(sockfd, &their_addr, &sin_size);printf(”對(duì)方地址: %sn, inet_ntoa(their_addr.sin_addr); 函數(shù)簡介:select應(yīng)用于多路同步I/O模式int select(int numfds, fd_set *readfds, fd_set *writefds, fd_set *e

14、xceptfds, struct timeval *timeout);numfds是要多路選擇的socket的最大值其中readfds, writefds, exceptfds都是socket集合,分別代表有數(shù)據(jù)可讀、有數(shù)據(jù)要寫、發(fā)生異常的socket集合。timeout是select的時(shí)間限制返回值:在socket集合中準(zhǔn)備好的socket個(gè)數(shù)socket集合 集合變量類型:fd_set 集合變量運(yùn)算宏: FD_ZERO(*set)清空socket集合 FD_SET(s, *set)將s加入socket集合 FD_CLR(s, *set)從socket集合去掉s FD_ISSET(s, *s

15、et)判斷s是否在socket集合中 常數(shù)FD_SETSIZE:集合元素的最多個(gè)數(shù)Select應(yīng)用舉例fd_set rset;/* 可讀的socket集合 */FD_ZERO(& rset);/* 清空rset集合 */FD_SET(sockfd, rset);/* 將sockfd 加入rset集合 */nready = select(maxfd+1, &rset, null, null, null);/* maxfd是已知的最大的socket */if (FD_ISSET(sockfd, &rset) 函數(shù)簡介:recv 用于TCP協(xié)議中接收信息int recv(in

16、t sockfd, void *buf, int len, int flags); buf,指向容納接收信息的緩沖區(qū)的指針 len,緩沖區(qū)的大小 flags,接收標(biāo)志 函數(shù)返回實(shí)際接收的字節(jié)數(shù),返回-1表示出錯(cuò) recv缺省是阻塞函數(shù),直到接收到信息或出錯(cuò)函數(shù)簡介:recvfrom 用于UDP協(xié)議中接收信息int recvfrom(int sockfd,void *buf,int len,unsigned int flagsstruct sockaddr *from, int *fromlen); buf,指向容納接收信息的緩沖區(qū)的指針 len,緩沖區(qū)的大小 flags,接收標(biāo)志 from,指

17、明接收數(shù)據(jù)的來源 函數(shù)返回實(shí)際接收的字節(jié)數(shù),返回-1表示出錯(cuò) recvfrom是阻塞函數(shù),直到接收到信息或出錯(cuò)函數(shù)簡介:send 用于TCP協(xié)議中發(fā)送信息int send(int sockfd, const void *msg, int len, int flags); msg,指向待發(fā)送信息的指針 len,待發(fā)送的字節(jié)數(shù) flags,發(fā)送標(biāo)志 函數(shù)返回已發(fā)送的字節(jié)數(shù),返回-1表示出錯(cuò) send缺省是阻塞函數(shù),直到發(fā)送完畢或出錯(cuò) 注意:如果函數(shù)返回值與參數(shù)len不相等,則剩余的未發(fā)送信息需要再次發(fā)送函數(shù)簡介:sendto 用于UDP協(xié)議中發(fā)送信息int sendto(int sockfd, c

18、onst void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen); buf,指向容納接收信息的緩沖區(qū)的指針 len,緩沖區(qū)的大小 flags,接收標(biāo)志 to,指明發(fā)送數(shù)據(jù)的目的地 函數(shù)返回已發(fā)送的字節(jié)數(shù),返回-1表示出錯(cuò) sendto缺省是阻塞函數(shù),直到發(fā)送完畢或出錯(cuò) 注意:如果函數(shù)返回值與參數(shù)len不相等,則剩余的未發(fā)送信息需要再次發(fā)送send, sendto, recv, recvfrom函數(shù)調(diào)用的參數(shù):flags MSG_DONTROUTE 對(duì)send, sendto有效 表示不使用路由(

19、一般不使用) MSG_PEEK 對(duì)recv, recvfrom有效 表示讀出網(wǎng)絡(luò)數(shù)據(jù)后不清除已讀的數(shù)據(jù) MSG_OOB 對(duì)發(fā)送接收都有效 表示讀/寫帶外數(shù)據(jù)(out-of-band data)函數(shù)簡介:close 關(guān)閉特定的socket連接 調(diào)用函數(shù):int close(int sockfd); 關(guān)閉連接將中斷對(duì)該socket的讀寫操作。 關(guān)閉用于listen()函數(shù)的socket將禁止其他Client的連接請(qǐng)求函數(shù)簡介:shutdown Shutdown()函數(shù)可以單方面的中斷連接,即禁止某個(gè)方向的信息傳遞。 函數(shù)調(diào)用int shutdown(int sockfd, int how);參數(shù)h

20、ow:0 - 禁止接收信息1 - 禁止發(fā)送信息2 - 接收和發(fā)送都被禁止,與close()函數(shù)效果相同返回0表示調(diào)用成功,返回-1表示出錯(cuò)函數(shù)簡介:ioctl 獲得或改變socket的I/O屬性int ioctl(int sockfd,long cmd,unsigned long* argp) cmd:屬性 argp:屬性的參數(shù)(緩存區(qū)指針) 常用的屬性: FIONREAD,返回socket緩沖區(qū)中未讀數(shù)據(jù)的字節(jié)數(shù) FIONBIO,argp為零時(shí)為阻塞模式,非零時(shí)為非阻塞模式 SIOCATMARK ,判斷是否有未讀的帶外數(shù)據(jù)(僅用 于TCP協(xié)議),返回true或false函數(shù)簡介:inet_a

21、ddr, inet_ntoa unsigned long inet_addr (const char *cp); inet_addr將一個(gè)點(diǎn)分十進(jìn)制IP地址字符串轉(zhuǎn)換成32位數(shù)字表示的IP地址 char* inet_ntoa (struct in_addr in); inet_ntoa將一個(gè)32位數(shù)字表示的IP地址轉(zhuǎn)換成點(diǎn)分十進(jìn)制IP地址字符串 這兩個(gè)函數(shù)互為反函數(shù)TCP:基于連接流的網(wǎng)絡(luò)協(xié)議 TCP相關(guān)的函數(shù) Server的例子 Client的例子 Server-Client結(jié)構(gòu)圖 TCP編程的適用范圍 TCP應(yīng)用舉例Server部分Server程序的作用 程序初始化 持續(xù)監(jiān)聽一個(gè)固定的端口

22、 收到Client的連接后建立一個(gè)socket連接 與Client進(jìn)行通信和信息處理 接收Client通過socket連接發(fā)送來的數(shù)據(jù),進(jìn)行相應(yīng)處理并返回處理結(jié)果,如BBS Server 通過socket連接向Client發(fā)送信息,如Time Server 通信結(jié)束后中斷與Client的連接 一個(gè)簡單的TCP Server完整的Server程序示例程序流程一 取得socket描述符:int sockfd;sockfd = socket(AF_INET, SOCK_STREAM, 0) ;程序流程二 填寫自身地址信息的sockaddr_in結(jié)構(gòu)struct sockaddr_in my_addr

23、; /* 自身的地址信息 */my_addr.sin_family = AF_INET; /* 網(wǎng)絡(luò)字節(jié)順序 */my_addr.sin_port = htons(MYPORT);/* 自動(dòng)填本機(jī)IP */my_addr.sin_addr.s_addr = INADDR_ANY;/* 其余部分置0 */bzero(&(my_addr.sin_zero), 8); 程序流程三 綁定端口bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr);程序流程四 監(jiān)聽端口#define BACKLOG 10liste

24、n(sockfd, BACKLOG);程序流程五 接受連接請(qǐng)求int new_fd; /* 數(shù)據(jù)端口 */struct sockaddr_in their_addr; /* 連接對(duì)方的地址信息 */int sin_size;sin_size = sizeof(struct sockaddr_in);new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)程序流程六 產(chǎn)生新進(jìn)程(線程)處理讀寫socketif (!fork() /* 子進(jìn)程 */if (send(new_fd, Hello, world!

25、 n, 14, 0) = -1) perror(send);close(new_fd);exit(0);close(new_fd);程序流程七 轉(zhuǎn)程序流程五,繼續(xù)等待其他Client的連接并處理#include #include #include #include #include #include #include #include #define MYPORT 3490 /* 監(jiān)聽端口 */#define BACKLOG 10 /* listen的請(qǐng)求接收隊(duì)列長度 */void main()int sockfd, new_fd; /* 監(jiān)聽端口,數(shù)據(jù)端口 */struct sockaddr

26、_in my_addr; /* 自身的地址信息 */struct sockaddr_in their_addr; /* 連接對(duì)方的地址信息 */int sin_size;if (sockfd = socket(AF_INET, SOCK_STREAM, 0) = -1) perror(socket);exit(1);my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); /* 網(wǎng)絡(luò)字節(jié)順序 */my_addr.sin_addr.s_addr = INADDR_ANY; /* 自動(dòng)填本機(jī)IP */bzero(&(my

27、_addr.sin_zero), 8); /* 其余部分置0 */if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr) = -1) perror(bind);exit(1);if (listen(sockfd, BACKLOG) = -1) perror(listen);exit(1);while(1) /* 主循環(huán) */sin_size = sizeof(struct sockaddr_in);new_fd = accept(sockfd, (struct sockaddr *)&their

28、_addr, &sin_size)if (new_fd = -1) perror(accept);continue;printf(”Got connection from %s n, inet_ntoa(their_addr.sin_addr);if (!fork() /* 子進(jìn)程 */if (send(new_fd, Hello, world! n, 14, 0) = -1) perror(send);close(new_fd);exit(0);close(new_fd); /* 無法生成子進(jìn)程時(shí)有用 */while(waitpid(-1,NULL,WNOHANG) 0); /*清除

29、所有子進(jìn)程 */ TCP應(yīng)用舉例Client部分Client程序的作用 程序初始化 連接到某個(gè)Server上,建立socket連接 與Server進(jìn)行通信和信息處理 接收Server通過socket連接發(fā)送來的數(shù)據(jù),進(jìn)行相應(yīng)處理 通過socket連接向Server發(fā)送請(qǐng)求信息 通信結(jié)束后中斷與Client的連接 一個(gè)簡單的TCP Client完整的Client程序示例程序流程一 取得socket描述符:int sockfd;sockfd = socket(AF_INET, SOCK_STREAM, 0);程序流程二 填寫連接對(duì)方的地址信息的sockaddr_in結(jié)構(gòu)struct hostent

30、 *he;struct sockaddr_in their_addr; /* 對(duì)方的地址信息 */he=gethostbyname(“”);their_addr.sin_family = AF_INET; their_addr.sin_port = htons(4000); /* short, NBO */their_addr.sin_addr = *(struct in_addr *)he-h_addr);bzero(&(their_addr.sin_zero), 8); /* 其余部分設(shè)置成0 */程序流程三 連接端口connect(sockfd, (s

31、truct sockaddr *)&their_addr, sizeof(struct sockaddr);程序流程四 讀寫socket程序流程五 關(guān)閉socketclose(sockfd);#include #include #include #include #include #include #include #include #define PORT 3490 /* Server的端口 */#define MAXDATASIZE 100/*一次可以讀的最大字節(jié)數(shù) */int main(int argc, char *argv)int sockfd, numbytes;char

32、bufMAXDATASIZE;struct hostent *he;/* 主機(jī)信息 */struct sockaddr_in their_addr; /* 對(duì)方地址信息 */if (argc != 2) fprintf(stderr,usage: client hostnamen);exit(1);if (he=gethostbyname(argv1) = NULL) /* get the host info */herror(gethostbyname);exit(1);if (sockfd=socket(AF_INET,SOCK_STREAM,0)=-1) perror(socket);e

33、xit(1);their_addr.sin_family = AF_INET; their_addr.sin_port = htons(PORT); /* short, NBO */their_addr.sin_addr = *(struct in_addr *)he-h_addr);bzero(&(their_addr.sin_zero), 8); /* 其余部分設(shè)成0 */if (connect(sockfd, (struct sockaddr *)&their_addr, sizeof(struct sockaddr) = -1) perror(connect);exit

34、(1);if (numbytes=recv(sockfd,buf,MAXDATASIZE,0)=-1) perror(recv);exit(1);bufnumbytes = 0;printf(Received: %s,buf);close(sockfd);return 0;TCP, C/S結(jié)構(gòu)圖:UDP:基于數(shù)據(jù)包的無連接協(xié)議 UDP與TCP的區(qū)別 Server的例子 Client的例子 Server-Client關(guān)系圖 UDP編程的適用范圍UDP與TCP的區(qū)別 基于連接與無連接 流模式與數(shù)據(jù)報(bào)模式 TCP保證數(shù)據(jù)正確性,UDP可能丟包 TCP保證數(shù)據(jù)順序,UDP不保證 對(duì)系統(tǒng)資源的要求(TC

35、P較多,UDP少)具體編程時(shí)的區(qū)別 socket()的參數(shù)不同 UDP Server不需要調(diào)用listen和accept UDP收發(fā)數(shù)據(jù)用sendto/recvfrom函數(shù) TCP:地址信息在connect/accept時(shí)確定UDP:在sendto/recvfrom函數(shù)中每次均需指定地址信息 UDP:shutdown函數(shù)無效UDP Server-Client關(guān)系圖 UDP應(yīng)用舉例Server部分#include #include #include #include #include #include #include #include #define MYPORT 3490 /* 監(jiān)聽端口 *

36、/void main()int sockfd; /* 數(shù)據(jù)端口 */struct sockaddr_in my_addr; /* 自身的地址信息 */struct sockaddr_in their_addr; /* 連接對(duì)方的地址信息 */int sin_size, retval;char buf128;if (sockfd = socket(AF_INET, SOCK_DGRAM, 0) = -1) perror(socket);exit(1);my_addr.sin_family = AF_INET; my_addr.sin_port = htons(MYPORT); /* 網(wǎng)絡(luò)字節(jié)順序

37、 */my_addr.sin_addr.s_addr = INADDR_ANY; /* 自動(dòng)填本機(jī)IP */bzero(&(my_addr.sin_zero), 8); /* 其余部分置0 */if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr) = -1) perror(bind);exit(1);while(1) /* 主循環(huán) */retval = recvfrom(sockfd, buf, 128, 0, (struct sockaddr *)&their_addr,&sin_size)

38、;printf(Received datagram from %sn,inet_ntoa(their_addr.sin_addr);if (retval = 0) perror (“recvfrom);close(sockfd);break;retval = sendto(sockfd, buf, 128, 0, (struct sockaddr *)&their_addr,sin_size); UDP應(yīng)用舉例Client部分#include #include #include #include #include #include #include #include #define P

39、ORT 3490 /* Server的端口 */#define MAXDATASIZE 100/*一次可以讀的最大字節(jié)數(shù) */int main(int argc, char *argv)int sockfd, numbytes, sin_size;char bufMAXDATASIZE = “Hello, world!”;struct hostent *he;/* 主機(jī)信息 */struct sockaddr_in their_addr; /* 對(duì)方地址信息 */if (argc != 2) fprintf(stderr,usage: client hostnamen);exit(1);if

40、(he=gethostbyname(argv1) = NULL) /* get the host info */herror(gethostbyname);exit(1);if (sockfd=socket(AF_INET,SOCK_DGRAM,0)=-1) perror(socket);exit(1);their_addr.sin_family = AF_INET; their_addr.sin_port = htons(PORT); /* short, NBO */their_addr.sin_addr = *(struct in_addr *)he-h_addr);bzero(&

41、(their_addr.sin_zero), 8); /* 其余部分設(shè)成0 */if (numbytes = sendto(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&their_addr,sizeof(their_addr)=-1) perror(“sendto);exit(1);printf(“Send: %s,buf);if (numbytes = recvfrom(sockfd, buf, MAXDATASIZE, 0, (struct sockaddr *)&their_addr, &sin_size)=-

42、1) perror(recvfrom);exit(1);bufnumbytes = 0;printf(Received: %s,buf);close(sockfd);return 0;UDP編程的適用范圍 部分滿足以下幾點(diǎn)要求時(shí),應(yīng)該用UDP 面向數(shù)據(jù)報(bào) 網(wǎng)絡(luò)數(shù)據(jù)大多為短消息 擁有大量Client 對(duì)數(shù)據(jù)安全性無特殊要求 網(wǎng)絡(luò)負(fù)擔(dān)非常重,但對(duì)響應(yīng)速度要求高 例子:ICQ、ping Linux網(wǎng)絡(luò)程序的設(shè)計(jì)主要針對(duì)TCP Server網(wǎng)絡(luò)編程 協(xié)議設(shè)計(jì) Server程序的設(shè)計(jì) 程序結(jié)構(gòu)的考慮 傳輸模式的考慮 網(wǎng)絡(luò)函數(shù)的考慮設(shè)計(jì)網(wǎng)絡(luò)協(xié)議 設(shè)計(jì)網(wǎng)絡(luò)協(xié)議目的 設(shè)計(jì)網(wǎng)絡(luò)協(xié)議時(shí)需要考慮的因素 完備性 正確

43、性 最簡性(簡便性)示例:Chat協(xié)議 協(xié)議分成兩組: 客戶端請(qǐng)求協(xié)議 服務(wù)器通知協(xié)議 發(fā)送協(xié)議后對(duì)方會(huì)返回一個(gè)數(shù)字表示錯(cuò)誤值,可以根據(jù)錯(cuò)誤值判斷是否完成操作和/或錯(cuò)誤類型客戶端請(qǐng)求協(xié)議 普通用戶命令:用戶申請(qǐng)登錄 0 x80 用戶退出 0 x81用戶加入房間 0 x82 用戶離開房間 0 x83給用戶發(fā)消息 0 x84 在房間中講話 0 x85取所有房間的信息 0 x86 取某一房間的信息 0 x87取所有用戶的信息 0 x88 取某一用戶的信息 0 x89 管理員命令:對(duì)所有用戶廣播0 x90踢出用戶0 x91增加房間管理員0 x92服務(wù)器通知協(xié)議用戶加入組0 xC0用戶離開組0 xC1傳

44、遞消息0 xC2用戶成為房間管理員0 xC3用戶被踢出房間0 xC4對(duì)協(xié)議代碼的返回值 0 x7F:無錯(cuò)誤(正確返回)。 0 xF0:無效的房間名稱。 0 xF1:無效的用戶名稱。 0 xF2:用戶登錄失敗。 0 xF3:當(dāng)前用戶沒有此項(xiàng)操作的權(quán)力。 0 xF4:達(dá)到最大房間數(shù),無法新建房間。 0 xF5:達(dá)到最大用戶數(shù),無法登錄。 0 xFE:無效協(xié)議代碼 0 xFF:其他錯(cuò)誤Server的設(shè)計(jì) 設(shè)計(jì)Server時(shí)需要考慮的因素 響應(yīng)速度(新建連接時(shí)、發(fā)送數(shù)據(jù)時(shí)) 運(yùn)行速度 I/O吞吐量 其它:流量控制(QoS)、安全性 針對(duì)特定協(xié)議的數(shù)據(jù)結(jié)構(gòu)設(shè)計(jì)Server的程序結(jié)構(gòu) 程序結(jié)構(gòu)的考慮 多線

45、程 多進(jìn)程 單進(jìn)程 網(wǎng)絡(luò)函數(shù)的考慮 TCP流模式 或 UDP數(shù)據(jù)報(bào)模式 阻塞函數(shù) 或 非阻塞函數(shù)程序結(jié)構(gòu):多進(jìn)程 在主進(jìn)程調(diào)用accept()函數(shù)生成一個(gè)新的連接后,調(diào)用fork()產(chǎn)生一個(gè)子進(jìn)程對(duì)這個(gè)新連接進(jìn)行操作 在主進(jìn)程結(jié)束前需要向所有子進(jìn)程發(fā)中斷信號(hào)并等待所有子進(jìn)程執(zhí)行完畢。 這種程序結(jié)構(gòu)最簡單,例子可以參照前面TCP Server的結(jié)構(gòu)和代碼。 主要應(yīng)用于各連接操作相互獨(dú)立的Server,可以保證各連接相互間的數(shù)據(jù)安全性, 如telnetd程序結(jié)構(gòu):多線程 基本與多進(jìn)程結(jié)構(gòu)類似,但是在獲得新連接時(shí)生成一個(gè)線程來對(duì)這個(gè)連接進(jìn)行處理。 主要的優(yōu)點(diǎn): 線程調(diào)度速度快,占用資源少 線程可共享進(jìn)程空間中的數(shù)據(jù) 主要應(yīng)用于各個(gè)連接之間關(guān)系較緊密的Server,例如:BBS Server Server的響應(yīng)速度和I/O吞吐

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(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)論