嵌入式Linux網(wǎng)絡(luò)編程之:網(wǎng)絡(luò)基礎(chǔ)編程
10.2網(wǎng)絡(luò)基礎(chǔ)編程
10.2.1socket概述
1.socket定義
在Linux中的網(wǎng)絡(luò)編程是通過(guò)socket接口來(lái)進(jìn)行的。人們常說(shuō)的socket是一種特殊的I/O接口,它也是一種文件描述符。socket是一種常用的進(jìn)程之間通信機(jī)制,通過(guò)它不僅能實(shí)現(xiàn)本地機(jī)器上的進(jìn)程之間的通信,而且通過(guò)網(wǎng)絡(luò)能夠在不同機(jī)器上的進(jìn)程之間進(jìn)行通信。
每一個(gè)socket都用一個(gè)半相關(guān)描述{協(xié)議、本地地址、本地端口}來(lái)表示;一個(gè)完整的套接字則用一個(gè)相關(guān)描述{協(xié)議、本地地址、本地端口、遠(yuǎn)程地址、遠(yuǎn)程端口}來(lái)表示。socket也有一個(gè)類(lèi)似于打開(kāi)文件的函數(shù)調(diào)用,該函數(shù)返回一個(gè)整型的socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^(guò)socket來(lái)實(shí)現(xiàn)的。
2.socket類(lèi)型
常見(jiàn)的socket有3種類(lèi)型如下。
(1)流式socket(SOCK_STREAM)。
流式套接字提供可靠的、面向連接的通信流;它使用TCP協(xié)議,從而保證了數(shù)據(jù)傳輸?shù)恼_性和順序性。
(2)數(shù)據(jù)報(bào)socket(SOCK_DGRAM)。
數(shù)據(jù)報(bào)套接字定義了一種無(wú)連接的服務(wù),數(shù)據(jù)通過(guò)相互獨(dú)立的報(bào)文進(jìn)行傳輸,是無(wú)序的,并且不保證是可靠、無(wú)差錯(cuò)的。它使用數(shù)據(jù)報(bào)協(xié)議UDP。
(3)原始socket。
原始套接字允許對(duì)底層協(xié)議如IP或ICMP進(jìn)行直接訪問(wèn),它功能強(qiáng)大但使用較為不便,主要用于一些協(xié)議的開(kāi)發(fā)。
10.2.2地址及順序處理
1.地址結(jié)構(gòu)相關(guān)處理
(1)數(shù)據(jù)結(jié)構(gòu)介紹。
下面首先介紹兩個(gè)重要的數(shù)據(jù)類(lèi)型:sockaddr和sockaddr_in,這兩個(gè)結(jié)構(gòu)類(lèi)型都是用來(lái)保存socket信息的,如下所示:
structsockaddr
{
unsignedshortsa_family;/*地址族*/
charsa_data[14];/*14字節(jié)的協(xié)議地址,包含該socket的IP地址和端口號(hào)。*/
};
structsockaddr_in
{
shortintsa_family;/*地址族*/
unsignedshortintsin_port;/*端口號(hào)*/
structin_addrsin_addr;/*IP地址*/
unsignedcharsin_zero[8];/*填充0以保持與structsockaddr同樣大小*/
};
這兩個(gè)數(shù)據(jù)類(lèi)型是等效的,可以相互轉(zhuǎn)化,通常sockaddr_in數(shù)據(jù)類(lèi)型使用更為方便。在建立socketadd或sockaddr_in后,就可以對(duì)該socket進(jìn)行適當(dāng)?shù)牟僮髁恕?/p>
(2)結(jié)構(gòu)字段。
表10.1列出了該結(jié)構(gòu)sa_family字段可選的常見(jiàn)值。
表10.1
結(jié)構(gòu)定義頭文件 | #includenetinet/in.h> |
sa_family | AF_INET:IPv4協(xié)議 |
AF_INET6:IPv6協(xié)議 | |
AF_LOCAL:UNIX域協(xié)議 | |
AF_LINK:鏈路地址協(xié)議 | |
AF_KEY:密鑰套接字(socket) |
sockaddr_in其他字段的含義非常清楚,具體的設(shè)置涉及其他函數(shù),在后面會(huì)有詳細(xì)的講解。
2.?dāng)?shù)據(jù)存儲(chǔ)優(yōu)先順序
(1)函數(shù)說(shuō)明。
計(jì)算機(jī)數(shù)據(jù)存儲(chǔ)有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先(稱(chēng)為大端模式)和低位字節(jié)優(yōu)先(稱(chēng)為小端模式,PC機(jī)通常采用小端模式)。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,因此在有些情況下,需要對(duì)這兩個(gè)字節(jié)存儲(chǔ)優(yōu)先順序進(jìn)行相互轉(zhuǎn)化。這里用到了4個(gè)函數(shù):htons()、ntohs()、htonl()和ntohl()。這4個(gè)地址分別實(shí)現(xiàn)網(wǎng)絡(luò)字節(jié)序和主機(jī)字節(jié)序的轉(zhuǎn)化,這里的h代表host,n代表network,s代表short,l代表long。通常16位的IP端口號(hào)用s代表,而IP地址用l來(lái)代表。
(2)函數(shù)格式說(shuō)明。
表10.2列出了這4個(gè)函數(shù)的語(yǔ)法格式。
表10.2 htons等函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 | #includenetinet/in.h> |
函數(shù)原型 | uint16_thtons(unit16_thost16bit) |
函數(shù)傳入值 | host16bit:主機(jī)字節(jié)序的16位數(shù)據(jù) |
host32bit:主機(jī)字節(jié)序的32位數(shù)據(jù) | |
net16bit:網(wǎng)絡(luò)字節(jié)序的16位數(shù)據(jù) | |
net32bit:網(wǎng)絡(luò)字節(jié)序的32位數(shù)據(jù) | |
函數(shù)返回值 | 成功:返回要轉(zhuǎn)換的字節(jié)序 |
出錯(cuò):-1 |
注意 | 調(diào)用該函數(shù)只是使其得到相應(yīng)的字節(jié)序,用戶(hù)不需清楚該系統(tǒng)的主機(jī)字節(jié)序和網(wǎng)絡(luò)字節(jié)序是否真正相等。如果是相同不需要轉(zhuǎn)換的話(huà),該系統(tǒng)的這些函數(shù)會(huì)定義成空宏。 |
3.地址格式轉(zhuǎn)化
(1)函數(shù)說(shuō)明。
通常用戶(hù)在表達(dá)地址時(shí)采用的是點(diǎn)分十進(jìn)制表示的數(shù)值(或者是以冒號(hào)分開(kāi)的十進(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()。由于IPv6是下一代互聯(lián)網(wǎng)的標(biāo)準(zhǔn)協(xié)議,因此,本書(shū)講解的函數(shù)都能夠同時(shí)兼容IPv4和IPv6,但在具體舉例時(shí)仍以IPv4為例。
這里inet_pton()函數(shù)是將點(diǎn)分十進(jìn)制地址映射為二進(jìn)制地址,而inet_ntop()是將二進(jìn)制地址映射為點(diǎn)分十進(jìn)制地址。
(2)函數(shù)格式。
表10.3列出了inet_pton函數(shù)的語(yǔ)法要點(diǎn)。
表10.3 inet_pton函數(shù)語(yǔ)法要點(diǎn)
所需頭文件 | #includearpa/inet.h> | |
函數(shù)原型 | intinet_pton(intfamily,constchar*strptr,void*addrptr) | |
函數(shù)傳入值 | family | AF_INET:IPv4協(xié)議 |
AF_INET6:IPv6協(xié)議 | ||
strptr:要轉(zhuǎn)化的值 | ||
addrptr:轉(zhuǎn)化后的地址 | ||
函數(shù)返回值 | 成功:0 | |
出錯(cuò):-1 |
linux相關(guān)文章:linux教程
評(píng)論