【正文】
本章小結(jié) ? 掌握嵌入式 Linux網(wǎng)絡(luò)開發(fā)的相關(guān) API函數(shù) ? 了解 TCP/IP層次模型的基本知識(shí),以及其中的重要協(xié)議 ? 掌握網(wǎng)絡(luò)基礎(chǔ)編程的相關(guān) API函數(shù),以及常見的開發(fā)流程 ? 掌握對套接字的高級編程,了解套接字的非阻塞訪問與多路復(fù)用處理 。 ? 下面是 使用 select()函數(shù)的服務(wù)器端源代碼 。 } …… 套接字高級編程 ? 使用多路復(fù)用 ? 使用 ftl()函數(shù)雖然可以實(shí)現(xiàn)非阻塞 I/O或信號(hào)驅(qū)動(dòng) I/O,但在實(shí)際使用時(shí)往往會(huì)對資源是否準(zhǔn)備完畢進(jìn)行循環(huán)測試,這樣就大大增加了不必要的 CPU資源的占用。 if (flags 0 || ftl(sockfd, F_SETFL, flags|O_NONBLOCK) 0) { perror(ftl)。 ? ? 異步 I/O:可將 cmd設(shè)置為 F_SETFL,將 lock設(shè)置為O_ASYNC。 ? 本節(jié)給出了兩種解決 I/O多路復(fù)用的解決方法,分別為 : ? 非阻塞訪問(使用 ftl()函數(shù)) ? 多路復(fù)用處理(使用 select()或 poll()函數(shù)) 套接字高級編程 ? 非阻塞訪問 ? 函數(shù) ftl()針對 socket編程提供了如下的編程特性。 ? ? 頭文件 ? include ? ? 函數(shù)原型 ? int gethostname( char* hostname, /*函數(shù)返回時(shí),保存主機(jī)的名字 */ ? size_t size); /*hostname指向的數(shù)組的長度 */ ? ? 函數(shù)返回值 ? 成功: 0 ? 出錯(cuò): 1 套接字相關(guān)的 API及應(yīng)用 ? 編程實(shí)例 s o c k e t 服 務(wù) 器 端 c l o s e s e n d / s e n d t o r e c v / r e c v f r o m a c c e p t l i s t e n b i n d s o c k e t c l o s e r e c v / r e c v f r o m s e n d / s e n d t o c o n n e c t客 戶 端b i n d使用 TCP協(xié)議 socket編程流程圖 套接字高級編程 ? 在實(shí)際情況中,人們往往遇到多個(gè)客戶端連接服務(wù)器端的情況。返回的這個(gè)名字可以被 gethostbyname函數(shù)使用,由此可以得到本地主機(jī)的 IP地址。 /*地址結(jié)構(gòu)的長度 */ ? ? 函數(shù)返回值 ? 成功: 0 ? 出錯(cuò): 1 ? 當(dāng)我們擁有了遠(yuǎn)程連接用戶的 IP地址,就可以使用 i_ntoa函數(shù)或者gethostbyname函數(shù)來輸出信息或是做進(jìn)一步的處理。該函數(shù)的語法要點(diǎn)如下所示。len)。 ? setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, amp。 ? opt = 1。/*參數(shù)的長度 */ ? int setsockopt( int sockfd, int level, int name, char* value, int* optlen)。 ? 這兩個(gè)函數(shù)的語法要點(diǎn)如下所示。 ? 當(dāng)套接字已經(jīng)打開但尚未有連接的時(shí)候用 setsocket函數(shù)在其上設(shè)定選項(xiàng)。 0表示不允許接收數(shù)據(jù); 1表示不允許發(fā)送數(shù)據(jù); 2表示和 close函數(shù)一樣,不允許任何操作(包括接收與發(fā)送)。其語法要點(diǎn)如下所示。 套接字相關(guān)的 API及應(yīng)用 ? close和 shutdown函數(shù) ? 如果希望對套接字的關(guān)閉進(jìn)行進(jìn)一步操作的話,可以使用 shutdown函數(shù)。 ? 執(zhí)行 close之后,套接字將不會(huì)再允許進(jìn)行讀操作和寫操作。 套接字相關(guān)的 API及應(yīng)用 ? close和 shutdown函數(shù) ? 程序進(jìn)行網(wǎng)絡(luò)傳輸完畢后,需要關(guān)閉這個(gè)套接字描述符所表示的連接。 ? ? 頭文件 ? include sys/ ? include sys/ ? ? 函數(shù)原型 ? int recvfrom( int sockfd, /*套接字描述符 */ ? void *buf, /*存放接收數(shù)據(jù)的緩沖區(qū) */ ? int len, /*數(shù)據(jù)長度 */ ? unsigned int flags, /*一般為 0*/ ? struct sockaddr *from, /*源機(jī)的 IP地址和端口號(hào)信息 */ ? int *tolen) /*地址長度 */ ? ? 函數(shù)返回值 ? 成功:接收的字節(jié)數(shù) ? 出錯(cuò): 1 ? 同樣的, recvfrom函數(shù)和 recv函數(shù)也基本一致。 ? ? 頭文件 ? include sys/ ? include sys/ ? ? 函數(shù)原型 ? int sendto( int sockfd, /*套接字描述符 */ ? const void *msg, /*指向要發(fā)送數(shù)據(jù)的指針 */ ? int len, /*數(shù)據(jù)長度 */ ? unsigned int flags, /*一般為 0*/ ? const struct sockaddr *to, /*目地機(jī)的 IP地址和端口號(hào)信息 */ ? int tolen) /*地址長度 */ ? ? 函數(shù)返回值 ? 成功:發(fā)送的字節(jié)數(shù) ? 出錯(cuò): 1 ? 可以看到,這個(gè)函數(shù)和 send函數(shù)基本一致,只是將遠(yuǎn)程主機(jī)的套接字地址結(jié)構(gòu)以參數(shù)to出現(xiàn)在參數(shù)中。 ? 因?yàn)閿?shù)據(jù)報(bào)套接字無法對遠(yuǎn)程主機(jī)進(jìn)行連接,在發(fā)送數(shù)據(jù)時(shí)用到的遠(yuǎn)程主機(jī)的 IP地址和端口,都以參數(shù)形式體現(xiàn)在函數(shù)的參數(shù)中。 套接字相關(guān)的 API及應(yīng)用 ? sendto和 recvfrom函數(shù) ? 這兩個(gè)函數(shù)是進(jìn)行無連接的 UDP通訊時(shí)使用的。 ? ...... ? ...... 套接字相關(guān)的 API及應(yīng)用 ? send、 recv函數(shù) ? recv函數(shù)的語法要點(diǎn)如下所示。 ? ...... ? ...... ? len = strlen(msg)。 ? char* msg = “Hello World!”。 send函數(shù)的語法要點(diǎn)如下。 套接字相關(guān)的 API及應(yīng)用 ? send、 recv函數(shù) ? 這兩個(gè)函數(shù)是最基本的,通過連接的流式套接字進(jìn)行通訊的函數(shù)。 ? 參數(shù) addr用于存儲(chǔ)連接成功的客戶端地址結(jié)構(gòu),參數(shù) addrlen用于存儲(chǔ)客戶端地址結(jié)構(gòu)占用的字節(jié)空間大小。 ? ? 頭文件 ? include sys/ ? ? 函數(shù)原型 ? int accept( int sockfd, /*套接字描述符 */ ? struct sockaddr *addr, /*客戶端地址 */ ? socklen_t *addrlen) /*地址長度 */ ? ? 函數(shù)返回值 ? 成功:新的套接字描述符 ? 出錯(cuò): 1 套接字相關(guān)的 API及應(yīng)用 ? accept函數(shù) ? 服務(wù)器進(jìn)程調(diào)用函數(shù) accept接收客戶端提交的連接申請,其中參數(shù)sockfd是一個(gè)由函數(shù) socket創(chuàng)建,函數(shù) bind命名,并調(diào)用函數(shù) listen進(jìn)入監(jiān)聽的套接字描述符。 套接字相關(guān)的 API及應(yīng)用 ? accept函數(shù) ? 服務(wù)器端套接字在進(jìn)入監(jiān)聽狀態(tài)后,必須通過調(diào)用 accept函數(shù)接收客戶進(jìn)程提交的連接請求,才能完成一個(gè)套接字的完整連接。其語法要點(diǎn)如下所示。 exit(1)。 if(connect(sockfd,(struct sockaddr*)amp。 bzero(amp。 = htons(SERVER_PORT)。 ? ? 頭文件 ? include sys/ ? ? 函數(shù)原型 ? int connect(int sockfd, /*套接字描述符 */ ? struct sockaddr *serv_addr, /*服務(wù)器端地址 */ ? int addrlen) /*地址長度 */ ? ? 函數(shù)返回值 ? 成功: 0 ? 出錯(cuò): 1 套接字相關(guān)的 A