當(dāng)前位置:首頁 > 嵌入式培訓(xùn) > 嵌入式學(xué)習(xí) > 講師博文 > Linux網(wǎng)絡(luò)編程之套接字
一 :套接字屬性
套接字由域(domain),類型(type)和協(xié)議(protocol)三個屬性確定其特性。
1)套接字的域
域指定套接字通信中使用的網(wǎng)絡(luò) 介質(zhì),常見的套接字域是AF_INET,它指的是互聯(lián)網(wǎng)絡(luò),許多LINUX局域網(wǎng)使用的都是該網(wǎng)絡(luò)。
服務(wù)器上可能同時有多個服務(wù)正在運行,客戶可以通過IP端口來指定一臺聯(lián)網(wǎng)機(jī)器上的某個特定服務(wù)。在系統(tǒng)內(nèi)部,端口通過分配一個唯一的16位整數(shù)來標(biāo)識,在系統(tǒng)外部,則需要通過IP地址和端口號的組合來確定。套接字作為通信的終點,它必須在開始通信之前綁定一個端口。
服務(wù)器在特定的端口等待客戶的連接,知名服務(wù)器所分配的端口號在所有LINUX和UNIX機(jī)器上都是一樣的,它們通常(但并不總是如此)小于1024,一般情況下,小于1024的端口號都是為系統(tǒng)服務(wù)保留的,并且所服務(wù)的進(jìn)程必須具有超級用戶權(quán)限。
其它可以使用的域如AF_UNIX,AF_ISO,AF_XFA等。
2)套接字類型
套接字有三種類型:流式套接字(SOCK_STREAM),數(shù)據(jù)報套接字(SOCK_DGRAM)及原始套接字。
1、流式套接字(SOCK_STREAM)
流式套接字提供的是一個有序,可靠,雙向字節(jié)流的連接。因此,發(fā)送的數(shù)據(jù)可以確保不會丟失,復(fù)制或亂序到達(dá),并且在這一過程 中發(fā)生的錯誤也不會顯示出來。流式套接字由類型SOCK_STREAM指定,它們是地AF_INET域中通過TCP/IP連接來實現(xiàn)的,它們也是AF_UNIX域中常用的套接字類型。
2、數(shù)據(jù)報套接字(SOCK_DGRAM)
與此相反 ,由SOCK_DGRAM指定的數(shù)據(jù)報套接字不建立和維持一個連接,它尋可以發(fā)送的數(shù)據(jù)報的長度有限制。數(shù)據(jù)報作為一個單獨的網(wǎng)絡(luò)消息被傳輸,它可能會丟失,復(fù)制或亂序到達(dá)。數(shù)據(jù)報套接字是在AF_INET域中通過UDP/IP連接來實現(xiàn)的,它提供的是一種無序的不可靠服務(wù),但從資源的角度來看,相對來說它們開銷比較小,因為不需要維持網(wǎng)絡(luò)連接,而且因為無需花費時間來建立連接,它們的速度也很快。
3、原始套接字
二 :套接字協(xié)議
只要底層傳輸機(jī)制允許不止一個協(xié)議來提供所要求的套接字類型,就可以為套接字選擇一個特定的協(xié)議。我們重點討論UNIX網(wǎng)絡(luò)套接字和文件系統(tǒng)套接字,它們不需要你 選擇一個特定的協(xié)議,只需要使用其默認(rèn)值即可。
三 :創(chuàng)建套接字
socket系統(tǒng)調(diào)用創(chuàng)建一個套接字并返回一個描述符,該描述符可以用來訪問該套接字。
#include < sys/types.h>
#include < sys/socket.h>
socket函數(shù)原型為:
int socket(int domain, int type, int protocol);
domain參數(shù)指定socket的類型,一般為AF_INET,type可以是SOCK_STREAM 或SOCK_DGRAM,分別表示TCP連接和UDP連接;protocol通常賦值"0"。Socket()調(diào)用返回一個整型socket描述符,你可 以在后面的調(diào)用使用它。
一旦通過socket調(diào)用返回一個socket描述符,你應(yīng)該將該socket與你本機(jī)上的一個端口相關(guān)聯(lián)(往往當(dāng)你在設(shè)計服務(wù)器端程序時需要調(diào)用該函數(shù)。隨后你就可以在該端口監(jiān)聽服務(wù)請求;而客戶端一般無須調(diào)用該函數(shù))。
五:套接字地址
每個套接字域都有其自己的地址格式。對于AF_INET域來說,套接字地址由結(jié)構(gòu)sockaddr_in來指定,該結(jié)構(gòu)在頭文件netinet/in.h中定義。
我們要討論的第一個結(jié)構(gòu)類型是:struct sockaddr,該類型是用來保存socket信息的:
struct sockaddr
{
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14 字節(jié)的協(xié)議地址 */
};
sa_family一般為AF_INET;sa_data則包含該socket的IP地址和端口號。
另外還有一種結(jié)構(gòu)類型:
struct sockaddr_in
{
short int sin_ family; /* 地址族 */
unsigned short int sin_port; /* 端口號 */
struct in_addr sin_addr; /* IP地址 */
unsigned char sin_zero[8]; /* 填充0 以保持與struct sockaddr同樣大小 */
};
這個結(jié)構(gòu)使用更為方便。sin_zero(它用來將sockaddr_in結(jié)構(gòu)填充到與struct sockaddr同樣的長度)應(yīng)該用bzero()或memset()函數(shù)將其置為零。指向sockaddr_in 的指針和指向sockaddr的指針可以相互轉(zhuǎn)換,這意味著如果一個函數(shù)所需參數(shù)類型是sockaddr時,你可以在函數(shù)調(diào)用的時候?qū)⒁粋指向 sockaddr_in的指針轉(zhuǎn)換為指向sockaddr的指針;或者相反。sin_family通常被賦AF_INET;sin_port和 sin_addr應(yīng)該轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)優(yōu)先順序 。
IP地址結(jié)構(gòu)struct in_addr被定義為:
struct in_addr
{
unsigned long int s_addr;
};
IP地址中的四個字節(jié)組成一個32位的值。
這是幾個字節(jié)順序轉(zhuǎn)換函數(shù):
htons()--"Host to Network Short" ; htonl()--"Host to Network Long"
ntohs()--"Network to Host Short" ; ntohl()--"Network to Host Long"
在這里,h表示"host" ,n表示"network",s 表示"short",l表示 "long"。