嵌入式軟件開發(fā)技術(shù):第6章 嵌入式Linux網(wǎng)絡(luò)編程_第1頁
嵌入式軟件開發(fā)技術(shù):第6章 嵌入式Linux網(wǎng)絡(luò)編程_第2頁
嵌入式軟件開發(fā)技術(shù):第6章 嵌入式Linux網(wǎng)絡(luò)編程_第3頁
嵌入式軟件開發(fā)技術(shù):第6章 嵌入式Linux網(wǎng)絡(luò)編程_第4頁
嵌入式軟件開發(fā)技術(shù):第6章 嵌入式Linux網(wǎng)絡(luò)編程_第5頁
已閱讀5頁,還剩73頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

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

文檔簡介

1

6.1TCP/IP概述6.2網(wǎng)絡(luò)基礎(chǔ)編程6.3網(wǎng)絡(luò)高級(jí)編程第6章嵌入式Linux網(wǎng)絡(luò)編程2

第6章嵌入式Linux網(wǎng)絡(luò)編程

本章將介紹嵌入式Linux網(wǎng)絡(luò)編程的基礎(chǔ)知識(shí)。由于網(wǎng)絡(luò)在嵌入式應(yīng)用系統(tǒng)中的應(yīng)用非常廣泛,基本上常見的應(yīng)用都會(huì)與網(wǎng)絡(luò)有關(guān),因此,掌握這一部分的內(nèi)容是非常重要的。經(jīng)過本章的學(xué)習(xí),讀者將會(huì)掌握TCP/IP協(xié)議的基礎(chǔ)知識(shí)、嵌入式Linux網(wǎng)絡(luò)編程方法、能夠獨(dú)立編寫客戶端、服務(wù)器端的通信程序。3

第6章嵌入式Linux網(wǎng)絡(luò)編程6.1TCP/IP概述了解:計(jì)算機(jī)網(wǎng)絡(luò)的基本概念,熟悉TCP/IP分層模型,理解在網(wǎng)絡(luò)編程中如何選擇TCP/UDP協(xié)議。6.2網(wǎng)絡(luò)基礎(chǔ)編程——本章重點(diǎn) 掌握:1個(gè)概念、2個(gè)結(jié)構(gòu)、2類函數(shù)、1個(gè)流程4

6.1.1TCP/IP的分層模型OSI協(xié)議參考模型,它是基于國際標(biāo)準(zhǔn)化組織(ISO)的建議發(fā)展起來的,它分為7個(gè)層次:應(yīng)用層、表示層、會(huì)話層、傳輸層、網(wǎng)絡(luò)層、數(shù)據(jù)鏈路層及物理層。這個(gè)7層的協(xié)議模型雖然規(guī)定得非常細(xì)致和完善,但在實(shí)際中卻得不到廣泛的應(yīng)用,其重要的原因之一就在于它過于復(fù)雜。但它仍是此后很多協(xié)議模型的基礎(chǔ)。與此相區(qū)別的TCP/IP協(xié)議模型將OSI的7層協(xié)議模型簡化為4層,從而更有利于實(shí)現(xiàn)和使用。6.1TCP/IP概述5

6.1.1TCP/IP的分層模型TCP/IP的協(xié)議參考模型和OSI協(xié)議參考模型的對(duì)應(yīng)關(guān)系如下圖:6.1TCP/IP概述6

6.1.1TCP/IP的分層模型TCP/IP的協(xié)議參考模型通訊示意圖6.1TCP/IP概述7

6.1.1TCP/IP的分層模型網(wǎng)絡(luò)接口層(NetworkInterfaceLayer) 網(wǎng)絡(luò)接口層是TCP/IP協(xié)議軟件的最底層,負(fù)責(zé)將二進(jìn)制流轉(zhuǎn)換為數(shù)據(jù)幀,并進(jìn)行數(shù)據(jù)幀的發(fā)送和接收。數(shù)據(jù)幀是網(wǎng)絡(luò)傳輸?shù)幕締卧?.1TCP/IP概述8

6.1.1TCP/IP的分層模型網(wǎng)絡(luò)層(InternetLayer)

網(wǎng)絡(luò)層負(fù)責(zé)在主機(jī)之間的通信中選擇數(shù)據(jù)包的傳輸路徑,即路由。當(dāng)網(wǎng)絡(luò)層接收到傳輸層的請(qǐng)求后,傳輸某個(gè)具有目的地址信息的分組。該層把分組封裝在IP數(shù)據(jù)包中,填入數(shù)據(jù)包的首部,使用路由算法來確定是直接交付數(shù)據(jù)包,還是把它傳遞給路由器,然后把數(shù)據(jù)包交給適當(dāng)?shù)木W(wǎng)絡(luò)接口進(jìn)行傳輸。 網(wǎng)絡(luò)層還要負(fù)責(zé)處理傳入的數(shù)據(jù)包,檢驗(yàn)其有效性,使用路由算法來決定應(yīng)該對(duì)數(shù)據(jù)包進(jìn)行本地處理還是應(yīng)該轉(zhuǎn)發(fā)。 如果數(shù)據(jù)包的目的機(jī)處于本機(jī)所在的網(wǎng)絡(luò),該層軟件就會(huì)除去數(shù)據(jù)包的首部,再選擇適當(dāng)?shù)膫鬏攲訁f(xié)議來處理這個(gè)分組。6.1TCP/IP概述9

6.1.1TCP/IP的分層模型傳輸層(TransportLayer)

傳輸層負(fù)責(zé)提供應(yīng)用程序之間的通信服務(wù)。這種通信又稱為端到端通信。傳輸層要系統(tǒng)地管理信息的流動(dòng),還要提供可靠的傳輸服務(wù),以確保數(shù)據(jù)到達(dá)無差錯(cuò)、無亂序。為了達(dá)到這個(gè)目的,傳輸層協(xié)議軟件要進(jìn)行協(xié)商,讓接收方回送確認(rèn)信息及讓發(fā)送方重發(fā)丟失的分組。傳輸層協(xié)議軟件把要傳輸?shù)臄?shù)據(jù)流劃分為分組,把每個(gè)分組連同目的地址交給網(wǎng)絡(luò)層去發(fā)送。6.1TCP/IP概述10

6.1.1TCP/IP的分層模型應(yīng)用層(ApplicationLayer)

應(yīng)用層是分層模型的最高層,在這個(gè)最高層中,用戶調(diào)用應(yīng)用程序通過TCP/IP互聯(lián)網(wǎng)來訪問可行的服務(wù)。與各個(gè)傳輸層協(xié)議交互的應(yīng)用程序負(fù)責(zé)接收和發(fā)送數(shù)據(jù)。每個(gè)應(yīng)用程序選擇適當(dāng)?shù)膫鬏敺?wù)類型,把數(shù)據(jù)按照傳輸層的格式要求封裝好向下層傳輸。6.1TCP/IP概述11

6.1.2TCP/IP的分層模型特點(diǎn)TCP/IP模型邊界特性TCP/IP分層模型中有兩大邊界特性:一個(gè)是地址邊界特性,它將IP邏輯地址與底層網(wǎng)絡(luò)的硬件地址分開;一個(gè)是操作系統(tǒng)邊界特性,它將網(wǎng)絡(luò)應(yīng)用與協(xié)議軟件分開。6.1TCP/IP概述12

6.1.2TCP/IP的分層模型特點(diǎn)IP層特性IP層作為通信子網(wǎng)的最高層,提供無連接的數(shù)據(jù)包傳輸機(jī)制,但I(xiàn)P協(xié)議并不能保證IP包傳遞的可靠性,IP的機(jī)制是點(diǎn)到點(diǎn)的。用IP進(jìn)行通信的主機(jī)或路由器位于同一物理網(wǎng)絡(luò),對(duì)等機(jī)器之間擁有直接的物理連接。TCP/IP設(shè)計(jì)原則之一是為包容各種物理網(wǎng)絡(luò)技術(shù),包容性主要體現(xiàn)在IP層中。各種物理網(wǎng)絡(luò)技術(shù)在幀或報(bào)文格式、地址格式等方面差別很大,TCP/IP的重要思想之一就是通過IP將各種底層網(wǎng)絡(luò)技術(shù)統(tǒng)一起來,達(dá)到屏蔽底層細(xì)節(jié),提供統(tǒng)一虛擬網(wǎng)的目的。6.1TCP/IP概述13

6.1.2TCP/IP的分層模型特點(diǎn)TCP/IP的可靠性特性在TCP/IP網(wǎng)絡(luò)中,IP采用無連接的數(shù)據(jù)報(bào)機(jī)制,對(duì)數(shù)據(jù)進(jìn)行“盡力而為”的傳遞機(jī)制,即只管將報(bào)文盡力傳送到目的主機(jī),無論傳輸正確與否,不做驗(yàn)證,不發(fā)確認(rèn),也不保證報(bào)文的順序。TCP/IP的可靠性體現(xiàn)在傳輸層協(xié)議之一的TCP協(xié)議。TCP協(xié)議提供面向連接的服務(wù),因?yàn)閭鬏攲邮嵌说蕉说?,所以TCP/IP的可靠性被稱為端到端可靠性。6.1TCP/IP概述14

6.1.2TCP/IP的分層模型特點(diǎn)TCP/IP的特點(diǎn)就是將不同的底層物理網(wǎng)絡(luò)、拓?fù)浣Y(jié)構(gòu)隱藏起來,向用戶和應(yīng)用程序提供通用、統(tǒng)一的網(wǎng)絡(luò)服務(wù)。這樣,從用戶的角度看,整個(gè)TCP/IP互聯(lián)網(wǎng)就是一個(gè)統(tǒng)一的整體,它獨(dú)立于具體的各種物理網(wǎng)絡(luò)技術(shù),能夠向用戶提供一個(gè)通用的網(wǎng)絡(luò)服務(wù)。6.1TCP/IP概述15

6.1.2TCP/IP核心協(xié)議在TCP/IP協(xié)議族中,有很多種協(xié)議。6.1TCP/IP概述16

6.1.2TCP/IP核心協(xié)議TCPTCP的上一層是應(yīng)用層,TCP向應(yīng)用層提供可靠的面向連接的數(shù)據(jù)流傳輸服務(wù),TCP數(shù)據(jù)傳輸實(shí)現(xiàn)了從一個(gè)應(yīng)用程序到另一個(gè)應(yīng)用程序的數(shù)據(jù)傳遞。它能提供高可靠性通信(即數(shù)據(jù)無誤、數(shù)據(jù)無丟失、數(shù)據(jù)無失序、數(shù)據(jù)無重復(fù)到達(dá)的通信。),應(yīng)用程序通過向TCP層提交數(shù)據(jù)接發(fā)送/收端的地址和端口號(hào)而實(shí)現(xiàn)應(yīng)用層的數(shù)據(jù)通信。通過IP的源/目的可以惟一地區(qū)分網(wǎng)絡(luò)中兩個(gè)設(shè)備的連接,通過socket的源/目的可以惟一地區(qū)分網(wǎng)絡(luò)中兩個(gè)應(yīng)用程序的連接。6.1TCP/IP概述17

6.1.2TCP/IP核心協(xié)議建立連接——三次握手TCP是面向連接的,所謂面向連接,就是當(dāng)計(jì)算機(jī)雙方通信時(shí)必需先建立連接,然后進(jìn)行數(shù)據(jù)通信,最后拆除連接三個(gè)過程。TCP在建立連接時(shí)又分三步:6.1TCP/IP概述18

6.1.2TCP/IP核心協(xié)議數(shù)據(jù)傳輸——滑窗協(xié)議:當(dāng)發(fā)送方傳送一個(gè)數(shù)據(jù)包時(shí),啟動(dòng)計(jì)時(shí)器。當(dāng)該數(shù)據(jù)包到達(dá)目的地后,接收方回送一個(gè)數(shù)據(jù)包,其中包含一個(gè)確認(rèn)序號(hào),意思是希望收到的下一個(gè)數(shù)據(jù)包的順序號(hào)。如果發(fā)送方的定時(shí)器在確認(rèn)信息到達(dá)之前超時(shí),那么發(fā)送方會(huì)重發(fā)該數(shù)據(jù)包。6.1TCP/IP概述19

6.1.2TCP/IP核心協(xié)議TCP數(shù)據(jù)包頭TCP數(shù)據(jù)包頭格式:6.1TCP/IP概述20

6.1.2TCP/IP核心協(xié)議UDPUDP即用戶數(shù)據(jù)報(bào)協(xié)議,是一種面向無連接的不可靠傳輸協(xié)議,不需要通過3次握手來建立一個(gè)連接,同時(shí),一個(gè)UDP應(yīng)用可同時(shí)作為應(yīng)用的客戶或服務(wù)器方。由于UDP協(xié)議并不需要建立一個(gè)明確的連接,因此建立UDP應(yīng)用要比建立TCP應(yīng)用簡單得多。UDP比TCP協(xié)議更為高效,也能更好地解決實(shí)時(shí)性的問題,如今,包括網(wǎng)絡(luò)視頻會(huì)議系統(tǒng)在內(nèi)的眾多的客戶/服務(wù)器模式的網(wǎng)絡(luò)應(yīng)用都使用UDP協(xié)議。6.1TCP/IP概述21

6.1.2TCP/IP核心協(xié)議UDP數(shù)據(jù)包頭6.1TCP/IP概述22

6.1.2TCP/IP核心協(xié)議▲協(xié)議選擇協(xié)議的選擇應(yīng)該考慮到數(shù)據(jù)可靠性需求、應(yīng)用的實(shí)時(shí)性和網(wǎng)絡(luò)的可靠性。對(duì)數(shù)據(jù)可靠性要求高的應(yīng)用需選擇TCP協(xié)議,而對(duì)數(shù)據(jù)的可靠性要求不那么高的應(yīng)用可選擇UDP傳送。TCP協(xié)議中的3次握手、重傳確認(rèn)等手段可以保證數(shù)據(jù)傳輸?shù)目煽啃裕褂肨CP協(xié)議會(huì)有較大的時(shí)延,因此不適合對(duì)實(shí)時(shí)性要求較高的應(yīng)用;而UDP協(xié)議則有很好的實(shí)時(shí)性。網(wǎng)絡(luò)狀況不是很好的情況下需選用TCP協(xié)議(如在廣域網(wǎng)等情況),網(wǎng)絡(luò)狀況很好的情況下選擇UDP協(xié)議可以減少網(wǎng)絡(luò)負(fù)荷。6.1TCP/IP概述23

6.2.1套接字(socket)概述套接字定義在Linux中的網(wǎng)絡(luò)編程是通過socket接口來進(jìn)行的。套接字(socket)是一種特殊的I/O接口,它也是一種文件描述符.

每一個(gè)socket都用一個(gè)半相關(guān)描述{協(xié)議、本地地址、本地端口}來表示;一個(gè)完整的套接字則用一個(gè)相關(guān)描述{協(xié)議、本地地址、本地端口、遠(yuǎn)程地址、遠(yuǎn)程端口}來表示。socket也有一個(gè)類似于打開文件的函數(shù)調(diào)用,該函數(shù)返回一個(gè)整型的socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^socket來實(shí)現(xiàn)的。6.2網(wǎng)絡(luò)基礎(chǔ)編程24

6.2.1套接字(socket)概述套接字類型流式套接字(SOCK_STREAM) 流式套接字提供可靠的、面向連接的通信流;它使用TCP協(xié)議,從而保證了數(shù)據(jù)傳輸?shù)目煽啃院晚樞蛐浴?shù)據(jù)報(bào)套接字(SOCK_DGRAM) 數(shù)據(jù)報(bào)套接字定義了一種無連接的服務(wù),數(shù)據(jù)通過相互獨(dú)立的報(bào)文進(jìn)行傳輸,是無序的,并且不保證是可靠、無差錯(cuò)的。它使用數(shù)據(jù)報(bào)協(xié)議UDP。原始套接字(SOCK_RAW) 原始套接字允許對(duì)底層協(xié)議如IP或ICMP進(jìn)行直接訪問,它功能強(qiáng)大但使用較為不便,主要用于一些協(xié)議的開發(fā)。6.2網(wǎng)絡(luò)基礎(chǔ)編程25

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理地址結(jié)構(gòu)處理structsockaddr{ unsignedshortsa_family;/*地址族*/ charsa_data[14];/*14字節(jié)的協(xié)議地址,包含該socket的IP地址和端口號(hào)。*/};6.2網(wǎng)絡(luò)基礎(chǔ)編程26

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理地址結(jié)構(gòu)處理structsockaddr_in{ shortintsa_family;/*地址族*/ unsignedshortintsin_port;/*端口號(hào)*/

structin_addrsin_addr;/*IP地址*/ unsignedcharsin_zero[8];/*填充0以保持與struct sockaddr同樣大小*/};這兩個(gè)數(shù)據(jù)類型是等效的,可以相互轉(zhuǎn)化,通常sockaddr_in數(shù)據(jù)類型使用更為方便。在建立socketadd或sockaddr_in后,就可以對(duì)該socket進(jìn)行適當(dāng)?shù)牟僮髁恕?.2網(wǎng)絡(luò)基礎(chǔ)編程27

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理地址結(jié)構(gòu)處理typedefuint32_tin_addr_t;structin_addr{in_addr_ts_addr;};6.2網(wǎng)絡(luò)基礎(chǔ)編程28

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理sa_family字段可選的常見值:6.2網(wǎng)絡(luò)基礎(chǔ)編程29

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理數(shù)據(jù)存儲(chǔ)優(yōu)先順序計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先(稱為大端模式)和低位字節(jié)優(yōu)先(稱為小端模式,PC機(jī)通常采用小端模式)。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,因此在有些情況下,需要對(duì)這兩個(gè)字節(jié)存儲(chǔ)優(yōu)先順序進(jìn)行相互轉(zhuǎn)化。htonl()

4字節(jié)主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序ntohl()

4字節(jié)網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序htons()

2字節(jié)主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序ntohs()

2字節(jié)網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序6.2網(wǎng)絡(luò)基礎(chǔ)編程30

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理數(shù)據(jù)存儲(chǔ)優(yōu)先順序6.2網(wǎng)絡(luò)基礎(chǔ)編程31

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理地址格式轉(zhuǎn)化用戶在表達(dá)地址時(shí)通常采用點(diǎn)分十進(jìn)制表示的數(shù)值字符串(或者是以冒號(hào)分開的十進(jìn)制IPv6地址),而在通常使用的socket編程中所使用的則是二進(jìn)制值,這就需要將這兩個(gè)數(shù)值進(jìn)行轉(zhuǎn)換。這里在IPv4中用到的函數(shù)有inet_aton()、inet_addr()和inet_ntoa(),而IPv4和IPv6兼容的函數(shù)有inet_pton()和inet_ntop()。inet_pton()函數(shù)是將點(diǎn)分十進(jìn)制地址字符串轉(zhuǎn)換為二進(jìn)制地址而inet_ntop()是inet_pton()的反向操作,將二進(jìn)制地址轉(zhuǎn)換為點(diǎn)分十進(jìn)制地址字符串。6.2網(wǎng)絡(luò)基礎(chǔ)編程32

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理inet_pton()函數(shù)格式:6.2網(wǎng)絡(luò)基礎(chǔ)編程33

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理inet_ntop()函數(shù)格式:6.2網(wǎng)絡(luò)基礎(chǔ)編程34

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換(了解)通常,人們?cè)谑褂眠^程中都不愿意記憶冗長的IP地址,尤其到IPv6時(shí),地址長度多達(dá)128位,那時(shí)就更加不可能一次次記憶那么長的IP地址了。因此,使用主機(jī)名將會(huì)是很好的選擇。在Linux中,同樣有一些函數(shù)可以實(shí)現(xiàn)主機(jī)名和地址的轉(zhuǎn)化,最為常見的有g(shù)ethostbyname、gethostbyaddr、getaddrinfo等,它們都可以實(shí)現(xiàn)IPv4和IPv6的地址和主機(jī)名之間的轉(zhuǎn)化。其中g(shù)ethostbyname是將主機(jī)名轉(zhuǎn)化為IP地址,gethostbyaddr則是逆操作,是將IP地址轉(zhuǎn)化為主機(jī)名,另外getaddrinfo還能實(shí)現(xiàn)自動(dòng)識(shí)別IPv4地址和IPv6地址。6.2網(wǎng)絡(luò)基礎(chǔ)編程35

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換gethostbyname()和gethostbyaddr()都涉及到一個(gè)hostent的結(jié)構(gòu)體structhostent{ char*h_name; /*正式主機(jī)名*/ char**h_aliases; /*主機(jī)別名*/ inth_addrtype; /*地址類型*/ inth_length; /*地址字節(jié)長度*/ char**h_addr_list; /*指向IPv4或IPv6的地址指針數(shù)組*/}6.2網(wǎng)絡(luò)基礎(chǔ)編程36

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換getaddrinfo()函數(shù)涉及到一個(gè)addrinfo的結(jié)構(gòu)體structaddrinfo{ intai_flags; /*AI_PASSIVE,AI_CANONNAME;*/ intai_family; /*地址族*/ intai_socktype; /*socket類型*/ intai_protocol; /*協(xié)議類型*/ size_tai_addrlen; /*地址字節(jié)長度*/ char*ai_canonname; /*主機(jī)名*/ structsockaddr*ai_addr; /*socketaddr結(jié)構(gòu)體*/ structaddrinfo*ai_next; /*下一個(gè)指針鏈表*/}6.2網(wǎng)絡(luò)基礎(chǔ)編程37

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換gethostbyname()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程38

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換getaddrinfo()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程39

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換addrinfo常見選項(xiàng):6.2網(wǎng)絡(luò)基礎(chǔ)編程40

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換addrinfo常見選項(xiàng):6.2網(wǎng)絡(luò)基礎(chǔ)編程41

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理名字地址轉(zhuǎn)換注意:

通常服務(wù)器端在調(diào)用getaddrinfo()之前,ai_flags設(shè)置AI_PASSIVE,用于bind()函數(shù)(用于端口和地址的綁定,后面會(huì)講到),主機(jī)名nodename通常會(huì)設(shè)置為NULL??蛻舳苏{(diào)用getaddrinfo()時(shí),ai_flags一般不設(shè)置AI_PASSIVE,但是主機(jī)名nodename和服務(wù)名servname(端口)則應(yīng)該不為空。getaddrinfo()使用示例6.2網(wǎng)絡(luò)基礎(chǔ)編程42

6.2.3套接字編程進(jìn)行socket編程的基本函數(shù)有socket、bind、listen、accept、send、sendto、recv、recvfrom這幾個(gè),其中對(duì)于客戶端和服務(wù)器端以及TCP和UDP的操作流程都有所區(qū)別,這里先對(duì)每個(gè)函數(shù)進(jìn)行一定的說明,再給出不同情況下使用的流程圖。6.2網(wǎng)絡(luò)基礎(chǔ)編程43

6.2.3套接字編程6.2網(wǎng)絡(luò)基礎(chǔ)編程socket:該函數(shù)用于建立一個(gè)套接字,一條通信路線的端點(diǎn)。在建立了socket之后,可對(duì)sockadd或sockaddr_in進(jìn)行初始化,以保存所建立的socket信息。socket()實(shí)際上指定了相關(guān)五元組中的協(xié)議這一元:SOCKETsocket(intaddr_family,intsocktype,intprotocol)bind:該函數(shù)用于綁定本地IP地址和端口號(hào),若綁定其他地址則不能成功。它主要用于TCP的連接,而在UDP的連接中則無必要。intbind(SOCKETs,conststructsockaddr*name,intnamelen)44

6.2.3套接字編程6.2網(wǎng)絡(luò)基礎(chǔ)編程listen:該函數(shù)在TCP中用于服務(wù)器端,表明它愿意接收連接intlisten(SOCKETs,intbacklog)backlog為允許的請(qǐng)求連接隊(duì)列長度。accept():

在TCP中用于服務(wù)器端,用于等待從SOCKETs上接受客戶連接請(qǐng)求(addr,addrlen為發(fā)送請(qǐng)求的客戶方信息):SOCKETaccept(SOCKETs,structsockaddr*addr,int*addrlen)45

6.2.3套接字編程6.2網(wǎng)絡(luò)基礎(chǔ)編程connect:該函數(shù)在TCP中用于bind的之后的client端,用于與服務(wù)器端建立連接,而在UDP中由于沒有了bind函數(shù),因此用connect有點(diǎn)類似bind函數(shù)的作用。intconnect(SOCKETs,conststructsockaddrname,intnamelen)send和recv:這兩個(gè)函數(shù)用于接收和發(fā)送數(shù)據(jù),可以用在TCP中,也可以用在UDP中。當(dāng)用在UDP時(shí),可以在connect函數(shù)建立連接之后再用。intsend(SOCKETs,constchar*buf,intlen,intflags)intrev(SOCKETs,char*buf,intlen,intflags)46

6.2.3套接字編程6.2網(wǎng)絡(luò)基礎(chǔ)編程sendto和recvfrom:這兩個(gè)函數(shù)的作用與send和recv函數(shù)類似,也可以用在TCP和UDP中。當(dāng)用在TCP時(shí),后面的幾個(gè)與地址有關(guān)參數(shù)不起作用,函數(shù)作用等同于send和recv;當(dāng)用在UDP時(shí),可以用在之前沒有使用connect的情況時(shí),這兩個(gè)函數(shù)可以自動(dòng)尋找指定地址并進(jìn)行連接。47

6.2.3套接字編程使用TCP時(shí)Socket編程6.2網(wǎng)絡(luò)基礎(chǔ)編程48

6.2.3套接字編程使用UDP時(shí)Socket編程6.2網(wǎng)絡(luò)基礎(chǔ)編程49

6.2.3套接字編程socket()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程50

6.2.3套接字編程bind()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程51

6.2.3套接字編程listen()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程52

6.2.3套接字編程accept()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程53

6.2.3套接字編程connect()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程54

6.2.3套接字編程send()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程55

6.2.3套接字編程recv()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程56

6.2.3套接字編程sendto()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程57

6.2.3套接字編程recvfrom()函數(shù)語法:6.2網(wǎng)絡(luò)基礎(chǔ)編程58

6.2.3套接字編程示例:分為服務(wù)器端和客戶端兩部分服務(wù)器端——先建立socket→與本地端口進(jìn)行綁定→接收客戶端的連接請(qǐng)求并建立與它的連接→接收客戶端發(fā)送的消息并顯示→退出??蛻舳恕ocket→與本地端口綁定→向服務(wù)器發(fā)送連接請(qǐng)求→向服務(wù)器發(fā)送消息→退出。6.2網(wǎng)絡(luò)基礎(chǔ)編程server.cclient.c59

第6章嵌入式Linux網(wǎng)絡(luò)編程6.2網(wǎng)絡(luò)基礎(chǔ)編程——重點(diǎn) 掌握:1個(gè)概念、2個(gè)結(jié)構(gòu)、2類函數(shù)、1個(gè)流程60

兩個(gè)結(jié)構(gòu)地址結(jié)構(gòu)處理structsockaddr{ unsignedshortsa_family;/*地址族*/ charsa_data[14];/*14字節(jié)的協(xié)議地址,包含該socket的IP地址和端口號(hào)。*/};6.2網(wǎng)絡(luò)基礎(chǔ)編程61

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理地址結(jié)構(gòu)處理structsockaddr_in{ shortintsa_family;/*地址族*/ unsignedshortintsin_port;/*端口號(hào)*/

structin_addrsin_addr;/*IP地址*/ unsignedcharsin_zero[8];/*填充0以保持與struct sockaddr同樣大小*/};這兩個(gè)數(shù)據(jù)類型是等效的,可以相互轉(zhuǎn)化,通常sockaddr_in數(shù)據(jù)類型使用更為方便。在建立socketadd或sockaddr_in后,就可以對(duì)該socket進(jìn)行適當(dāng)?shù)牟僮髁恕?.2網(wǎng)絡(luò)基礎(chǔ)編程62

6.2.2地址及數(shù)據(jù)存儲(chǔ)順序處理地址結(jié)構(gòu)處理typedefuint32_tin_addr_t;structin_addr{in_addr_ts_addr;};6.2網(wǎng)絡(luò)基礎(chǔ)編程63

兩類函數(shù)數(shù)據(jù)存儲(chǔ)優(yōu)先順序htonl()

4字節(jié)主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序ntohl()

4字節(jié)網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序htons()

2字節(jié)主機(jī)字節(jié)序轉(zhuǎn)換為網(wǎng)絡(luò)字節(jié)序ntohs()

2字節(jié)網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換為主機(jī)字節(jié)序6.2網(wǎng)絡(luò)基礎(chǔ)編程64

兩類函數(shù)地址格式轉(zhuǎn)化用戶在表達(dá)地址時(shí)通常采用點(diǎn)分十進(jìn)制表示的數(shù)值字符串(或者是以冒號(hào)分開的十進(jìn)制IPv6地址),而在通常使用的socket編程中所使用的則是二進(jìn)制值,這就需要將這兩個(gè)數(shù)值進(jìn)行轉(zhuǎn)換。這里在IPv4中用到的函數(shù)有inet_aton()、inet_addr()和inet_ntoa(),而IPv4和IPv6兼容的函數(shù)有inet_pton()和inet_ntop()。inet_pton()函數(shù)是將點(diǎn)分十進(jìn)制地址字符串轉(zhuǎn)換為二進(jìn)制地址而inet_ntop()是inet_pton()的反向操作,將二進(jìn)制地址轉(zhuǎn)換為點(diǎn)分十進(jìn)制地址字符串。6.2網(wǎng)絡(luò)基礎(chǔ)編程65

inet_pton()函數(shù)格式:6.2網(wǎng)絡(luò)基礎(chǔ)編程66

inet_ntop()函數(shù)格式:6.2網(wǎng)絡(luò)基礎(chǔ)編程67

一個(gè)流程:使用TCP時(shí)Socket編程6.2網(wǎng)絡(luò)基礎(chǔ)編程68

6.2.3套接字編程示例:分為服務(wù)器端和客戶端兩部分服務(wù)器端——先建立socket→與本地端口進(jìn)行綁定→接收客戶端的連接請(qǐng)求并建立與它的連接→接收客戶端發(fā)送的消息并顯示→退出??蛻舳恕ocket→與本地端口綁定→向服務(wù)器發(fā)送連接請(qǐng)求→向服務(wù)器發(fā)送消息→退出。6.2網(wǎng)絡(luò)基礎(chǔ)編程server.cclient.c69

改進(jìn)上述程序:1)服務(wù)器端顯示與之建立連接的客戶端的地址信息。2)客戶端指定端口。3)實(shí)現(xiàn)雙方多次發(fā)送/接收消息。6.2網(wǎng)絡(luò)基礎(chǔ)編程70

實(shí)戰(zhàn):多進(jìn)程和多線程是網(wǎng)絡(luò)編程中常用的事務(wù)處理方法。在示例程序的基礎(chǔ)上,使用多進(jìn)程或多線程技術(shù),編程實(shí)現(xiàn)一個(gè)全雙工的網(wǎng)絡(luò)聊天程序。6.2網(wǎng)絡(luò)基礎(chǔ)編程71

在實(shí)際情況中,人們往往需要處理多個(gè)客戶端連接服務(wù)器的情況。而之前的實(shí)例中使用用阻塞函數(shù),因此如果資源沒有準(zhǔn)備好,則調(diào)用該函數(shù)的進(jìn)程將進(jìn)入睡眠狀態(tài),無法處理其他請(qǐng)求。本節(jié)將討論3種解決I/O多路利用的解決方法,分別為非阻塞和異步式處理(使用fcntl()函數(shù))以及多路復(fù)用(使用select()和poll()函數(shù))。6.3網(wǎng)絡(luò)高級(jí)編程72

非阻塞和異步I/O

在socket編程中可以使用函數(shù)fcntl(intfd,intcmd,intarg)的如下的編程特性。獲得文件狀態(tài)標(biāo)志:將cmd設(shè)置為F_GETFL,會(huì)返回由fd指向的文件的狀態(tài)標(biāo)志(使用open函數(shù)打開文件時(shí)設(shè)置的flags)。非阻塞I/O:將cmd設(shè)置為F_SETFL,將arg設(shè)置為O_NONBLOCK。異步I/O:將cmd設(shè)置為F_SETFL,將arg設(shè)置為O_ASYNC

6.3網(wǎng)絡(luò)高級(jí)編程73

非阻塞I/O

示例:如何設(shè)置文件狀態(tài)標(biāo)志

intflag flag=fcntl(sockfd,F_GETFL,0); flag|=O_NONBLOCK; fcntl(sockfd,

溫馨提示

  • 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)論