亚洲av成人无遮挡网站在线观看,少妇性bbb搡bbb爽爽爽,亚洲av日韩精品久久久久久,兔费看少妇性l交大片免费,无码少妇一区二区三区

  免費(fèi)注冊 查看新帖 |

Chinaunix

  平臺 論壇 博客 文庫
最近訪問板塊 發(fā)新帖
查看: 1401 | 回復(fù): 0
打印 上一主題 下一主題

Linux Socket編程終極者 [復(fù)制鏈接]

論壇徽章:
0
跳轉(zhuǎn)到指定樓層
1 [收藏(0)] [報告]
發(fā)表于 2009-08-01 15:20 |只看該作者 |倒序瀏覽

什么是Socket
   Socket接口是TCP/IP網(wǎng)絡(luò)的API,Socket接口定義了許多函數(shù)或例程,程序員可以用它們來開發(fā)TCP/IP網(wǎng)絡(luò)上的應(yīng)用程序。要學(xué)Internet上的TCP/IP網(wǎng)絡(luò)編程,必須理解Socket接口。
    Socket接口設(shè)計者最先是將接口放在Unix操作系統(tǒng)里面的。如果了解Unix系統(tǒng)的輸入和輸出的話,就很容易了解Socket了。網(wǎng)絡(luò)的 Socket數(shù)據(jù)傳輸是一種特殊的I/O,Socket也是一種文件描述符。Socket也具有一個類似于打開文件的函數(shù)調(diào)用Socket(),該函數(shù)返 回一個整型的Socket描述符,隨后的連接建立、數(shù)據(jù)傳輸?shù)炔僮鞫际峭ㄟ^該Socket實現(xiàn)的。常用的Socket類型有兩種:流式Socket (SOCK_STREAM)和數(shù)據(jù)報式Socket(SOCK_DGRAM)。流式是一種面向連接的Socket,針對于面向連接的TCP服務(wù)應(yīng)用;數(shù)據(jù) 報式Socket是一種無連接的Socket,對應(yīng)于無連接的UDP服務(wù)應(yīng)用。

1.Socket建立
  為了建立Socket,程序可以調(diào)用Socket函數(shù),該函數(shù)返回一個類似于文件描述符的句柄。socket函數(shù)原型為:
   int socket(int domain, int type, int protocol);
    domain指明所使用的協(xié)議族,通常為PF_INET,表示互聯(lián)網(wǎng)協(xié)議族(TCP/IP協(xié)議族);type參數(shù)指定socket的類型: SOCK_STREAM 或SOCK_DGRAM,Socket接口還定義了原始Socket(SOCK_RAW),允許程序使用低層協(xié)議;protocol通常賦值"0"。 Socket()調(diào)用返回一個整型socket描述符,你可以在后面的調(diào)用使用它。
   Socket描述符是一個指向內(nèi)部數(shù)據(jù)結(jié)構(gòu)的指針,它指向描述符表入口。調(diào)用Socket函數(shù)時,socket執(zhí)行體將建立一個Socket,實際上"建立一個Socket"意味著為一個Socket數(shù)據(jù)結(jié)構(gòu)分配存儲空間。Socket執(zhí)行體為你管理描述符表。
  兩個網(wǎng)絡(luò)程序之間的一個網(wǎng)絡(luò)連接包括五種信息:通信協(xié)議、本地協(xié)議地址、本地主機(jī)端口、遠(yuǎn)端主機(jī)地址和遠(yuǎn)端協(xié)議端口。Socket數(shù)據(jù)結(jié)構(gòu)中包含這五種信息。

2.Socket配置
   通過socket調(diào)用返回一個socket描述符后,在使用socket進(jìn)行網(wǎng)絡(luò)傳輸以前,必須配置該socket。面向連接的socket客戶端通過調(diào)用Connect函數(shù)在socket數(shù)據(jù)結(jié)構(gòu)中保存本地和遠(yuǎn)端信息。無連接socket的客戶端和服務(wù)端以及面向連接socket的服務(wù)端通過調(diào)用 bind函數(shù)來配置本地信息。
Bind函數(shù)將socket與本機(jī)上的一個端口相關(guān)聯(lián),隨后你就可以在該端口監(jiān)聽服務(wù)請求。Bind函數(shù)原型為:
   int bind(int sockfd,struct sockaddr *my_addr, int addrlen);
   Sockfd是調(diào)用socket函數(shù)返回的socket描述符,my_addr是一個指向包含有本機(jī)IP地址及端口號等信息的sockaddr類型的指針;addrlen常被設(shè)置為sizeof(struct sockaddr)。
   struct sockaddr結(jié)構(gòu)類型是用來保存socket信息的:
   struct sockaddr {
   unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14 字節(jié)的協(xié)議地址 */
};
   sa_family一般為AF_INET,代表Internet(TCP/IP)地址族;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同樣的長度,可以用bzero()或memset()函數(shù)將其置為零。指向sockaddr_in 的指針和指向sockaddr的指針可以相互轉(zhuǎn)換,這意味著如果一個函數(shù)所需參數(shù)類型是sockaddr時,你可以在函數(shù)調(diào)用的時候?qū)⒁粋指向 sockaddr_in的指針轉(zhuǎn)換為指向sockaddr的指針;或者相反。
  使用bind函數(shù)時,可以用下面的賦值實現(xiàn)自動獲得本機(jī)IP地址和隨機(jī)獲取一個沒有被占用的端口號:
   my_addr.sin_port = 0; /* 系統(tǒng)隨機(jī)選擇一個未被使用的端口號 */
   my_addr.sin_addr.s_addr = INADDR_ANY; /* 填入本機(jī)IP地址 */
通過將my_addr.sin_port置為0,函數(shù)會自動為你選擇一個未占用的端口來使用。同樣,通過將my_addr.sin_addr.s_addr置為INADDR_ANY,系統(tǒng)會自動填入本機(jī)IP地址。
注意在使用bind函數(shù)是需要將sin_port和sin_addr轉(zhuǎn)換成為網(wǎng)絡(luò)字節(jié)優(yōu)先順序;而sin_addr則不需要轉(zhuǎn)換。
  計算機(jī)數(shù)據(jù)存儲有兩種字節(jié)優(yōu)先順序:高位字節(jié)優(yōu)先和低位字節(jié)優(yōu)先。Internet上數(shù)據(jù)以高位字節(jié)優(yōu)先順序在網(wǎng)絡(luò)上傳輸,所以對于在內(nèi)部是以低位字節(jié)優(yōu)先方式存儲數(shù)據(jù)的機(jī)器,在Internet上傳輸數(shù)據(jù)時就需要進(jìn)行轉(zhuǎn)換,否則就會出現(xiàn)數(shù)據(jù)不一致。
   下面是幾個字節(jié)順序轉(zhuǎn)換函數(shù):
·htonl():把32位值從主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
·htons():把16位值從主機(jī)字節(jié)序轉(zhuǎn)換成網(wǎng)絡(luò)字節(jié)序
·ntohl():把32位值從網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序
·ntohs():把16位值從網(wǎng)絡(luò)字節(jié)序轉(zhuǎn)換成主機(jī)字節(jié)序
   Bind()函數(shù)在成功被調(diào)用時返回0;出現(xiàn)錯誤時返回"-1"并將errno置為相應(yīng)的錯誤號。需要注意的是,在調(diào)用bind函數(shù)時一般不要將端口號置為小于1024的值,因為1到1024是保留端口號,你可以選擇大于1024中的任何一個沒有被占用的端口號。

3.連接建立
  面向連接的客戶程序使用Connect函數(shù)來配置socket并與遠(yuǎn)端服務(wù)器建立一個TCP連接,其函數(shù)原型為:
   int connect(int sockfd, struct sockaddr *serv_addr,int addrlen);
Sockfd 是socket函數(shù)返回的socket描述符;serv_addr是包含遠(yuǎn)端主機(jī)IP地址和端口號的指針;addrlen是遠(yuǎn)端地質(zhì)結(jié)構(gòu)的長度。 Connect函數(shù)在出現(xiàn)錯誤時返回-1,并且設(shè)置errno為相應(yīng)的錯誤碼。進(jìn)行客戶端程序設(shè)計無須調(diào)用bind(),因為這種情況下只需知道目的機(jī)器 的IP地址,而客戶通過哪個端口與服務(wù)器建立連接并不需要關(guān)心,socket執(zhí)行體為你的程序自動選擇一個未被占用的端口,并通知你的程序數(shù)據(jù)什么時候到 打斷口。
   Connect函數(shù)啟動和遠(yuǎn)端主機(jī)的直接連接。只有面向連接的客戶程序使用socket時才需要將此socket與遠(yuǎn)端主機(jī)相連。無連接協(xié)議從不建立直接連接。面向連接的服務(wù)器也從不啟動一個連接,它只是被動的在協(xié)議端口監(jiān)聽客戶的請求。
   Listen函數(shù)使socket處于被動的監(jiān)聽模式,并為該socket建立一個輸入數(shù)據(jù)隊列,將到達(dá)的服務(wù)請求保存在此隊列中,直到程序處理它們。
   int listen(int sockfd, int backlog);
Sockfd 是Socket系統(tǒng)調(diào)用返回的socket 描述符;backlog指定在請求隊列中允許的最大請求數(shù),進(jìn)入的連接請求將在隊列中等待accept()它們(參考下文)。Backlog對隊列中等待 服務(wù)的請求的數(shù)目進(jìn)行了限制,大多數(shù)系統(tǒng)缺省值為20。如果一個服務(wù)請求到來時,輸入隊列已滿,該socket將拒絕連接請求,客戶將收到一個出錯信息。
當(dāng)出現(xiàn)錯誤時listen函數(shù)返回-1,并置相應(yīng)的errno錯誤碼。
   accept()函數(shù)讓服務(wù)器接收客戶的連接請求。在建立好輸入隊列后,服務(wù)器就調(diào)用accept函數(shù),然后睡眠并等待客戶的連接請求。
   int accept(int sockfd, void *addr, int *addrlen);
    sockfd是被監(jiān)聽的socket描述符,addr通常是一個指向sockaddr_in變量的指針,該變量用來存放提出連接請求服務(wù)的主機(jī)的信息(某 臺主機(jī)從某個端口發(fā)出該請求);addrten通常為一個指向值為sizeof(struct sockaddr_in)的整型指針變量。出現(xiàn)錯誤時accept函數(shù)返回-1并置相應(yīng)的errno值。
  首先,當(dāng)accept函數(shù)監(jiān)視的 socket收到連接請求時,socket執(zhí)行體將建立一個新的socket,執(zhí)行體將這個新socket和請求連接進(jìn)程的地址聯(lián)系起來,收到服務(wù)請求的 初始socket仍可以繼續(xù)在以前的 socket上監(jiān)聽,同時可以在新的socket描述符上進(jìn)行數(shù)據(jù)傳輸操作。

4.數(shù)據(jù)傳輸
   Send()和recv()這兩個函數(shù)用于面向連接的socket上進(jìn)行數(shù)據(jù)傳輸。
   Send()函數(shù)原型為:
   int send(int sockfd, const void *msg, int len, int flags);
Sockfd是你想用來傳輸數(shù)據(jù)的socket描述符;msg是一個指向要發(fā)送數(shù)據(jù)的指針;Len是以字節(jié)為單位的數(shù)據(jù)的長度;flags一般情況下置為0(關(guān)于該參數(shù)的用法可參照man手冊)。
   Send()函數(shù)返回實際上發(fā)送出的字節(jié)數(shù),可能會少于你希望發(fā)送的數(shù)據(jù)。在程序中應(yīng)該將send()的返回值與欲發(fā)送的字節(jié)數(shù)進(jìn)行比較。當(dāng)send()返回值與len不匹配時,應(yīng)該對這種情況進(jìn)行處理。
char *msg = "Hello!";
int len, bytes_sent;
……
len = strlen(msg);
bytes_sent = send(sockfd, msg,len,0);
……
   recv()函數(shù)原型為:
   int recv(int sockfd,void *buf,int len,unsigned int flags);
   Sockfd是接受數(shù)據(jù)的socket描述符;buf 是存放接收數(shù)據(jù)的緩沖區(qū);len是緩沖的長度。Flags也被置為0。Recv()返回實際上接收的字節(jié)數(shù),當(dāng)出現(xiàn)錯誤時,返回-1并置相應(yīng)的errno值。
Sendto()和recvfrom()用于在無連接的數(shù)據(jù)報socket方式下進(jìn)行數(shù)據(jù)傳輸。由于本地socket并沒有與遠(yuǎn)端機(jī)器建立連接,所以在無連接的數(shù)據(jù)報發(fā)送數(shù)據(jù)時應(yīng)指明目的地址。
sendto()函數(shù)原型為:
   int sendto(int sockfd, const void *msg,int len,unsigned int flags,const struct sockaddr *to, int tolen);
  該函數(shù)比send()函數(shù)多了兩個參數(shù),to表示目地機(jī)的IP地址和端口號信息,而tolen常常被賦值為sizeof (struct sockaddr)。Sendto 函數(shù)也返回實際發(fā)送的數(shù)據(jù)字節(jié)長度或在出現(xiàn)發(fā)送錯誤時返回-1。
   Recvfrom()函數(shù)原型為:
   int recvfrom(int sockfd,void *buf,int len,unsigned int flags,struct sockaddr *from,int *fromlen);
    from是一個struct sockaddr類型的變量,該變量保存源機(jī)的IP地址及端口號。fromlen常置為sizeof (struct sockaddr)。當(dāng)recvfrom()返回時,fromlen包含實際存入from中的數(shù)據(jù)字節(jié)數(shù)。Recvfrom()函數(shù)返回接收到的字節(jié)數(shù)或 當(dāng)出現(xiàn)錯誤時返回-1,并置相應(yīng)的errno。
如果你對數(shù)據(jù)報socket調(diào)用了connect()函數(shù)時,你也可以利用send()和recv()進(jìn)行數(shù)據(jù)傳輸,但該socket仍然是數(shù)據(jù)報socket,并且利用傳輸層的UDP服務(wù)。但在發(fā)送或接收數(shù)據(jù)報時,內(nèi)核會自動為之加上目地和源地址信息。

5.結(jié)束傳輸
當(dāng)所有的數(shù)據(jù)操作結(jié)束以后,你可以調(diào)用close()函數(shù)來釋放該socket,從而停止在該socket上的任何數(shù)據(jù)操作:
close(sockfd);
  你也可以調(diào)用shutdown()函數(shù)來關(guān)閉該socket。該函數(shù)允許你只停止在某個方向上的數(shù)據(jù)傳輸,而一個方向上的數(shù)據(jù)傳輸繼續(xù)進(jìn)行。如你可以關(guān)閉某socket的寫操作而允許繼續(xù)在該socket上接受數(shù)據(jù),直至讀入所有數(shù)據(jù)。
   int shutdown(int sockfd,int how);
   Sockfd是需要關(guān)閉的socket的描述符。參數(shù) how允許為shutdown操作選擇以下幾種方式:
   ·0-------不允許繼續(xù)接收數(shù)據(jù)
   ·1-------不允許繼續(xù)發(fā)送數(shù)據(jù)
   ·2-------不允許繼續(xù)發(fā)送和接收數(shù)據(jù),
   ·均為允許則調(diào)用close ()
   shutdown在操作成功時返回0,在出現(xiàn)錯誤時返回-1并置相應(yīng)errno。

第四章 套接口的類型與協(xié)議
4.1指定套接口的域
在函數(shù)socketpair與socket的domain參數(shù)中有AF_UNIX,AF_LOCAL,AF_INET,PF_UNIX,PF_LOCAL,PF_INET.
這幾個參數(shù)有AF_UNIX=AF_LOCAL, PF_UNIX=PF_LOCAL, AF_LOCAL=PF_LOCAL, AF_INET=PF_INET.
**建議:對于socketpair與socket的domain參數(shù),使用PF_LOCAL系列,而在初始化套接口地址結(jié)構(gòu)時,則使用AF_LOCAL.
例如:
     z = socket(PF_LOCAL, SOCK_STREAM, 0);
     adr_unix.sin_family = AF_LOCAL;
4.3選擇套接口
在函數(shù)socketpair與socket中選擇代表協(xié)議族的參數(shù)domain:
-PF_LOCAL:表明指定的協(xié)議族是本地UNIX協(xié)議族
-PF_INET:表明指定的是Internet協(xié)議族
在函數(shù)socketpair與socket中type的參數(shù):
-SOCK_STREAM:常用
-SOCK_DGRAM:常用
-SOCK_SEQPACKET:X.25,AX.25使用
-SOCK_RW:表示編程者要一個原始(raw)套接口界面.可以對通信和分組進(jìn)行更直接的控制,但它要編程式者對協(xié)議和底層分組結(jié)構(gòu)非常熟悉.本書沒有介紹.略.....
4.3.1 SOCK_STREAM套接口
    套接口中的流與UNIX中管道的概念相近.
    字節(jié)流中沒有分界線,也沒有邊界;沒有記錄的長度工塊的大小,在接收端也不存在分組的概念,在接收端獲得的所有數(shù)據(jù)都返回到調(diào)用者的緩沖區(qū)中.
    例如:
        1)本地進(jìn)程寫入25字節(jié)數(shù)據(jù),通過套接口發(fā)到遠(yuǎn)程進(jìn)程
        2)本地進(jìn)程再寫30字節(jié)數(shù)據(jù),發(fā)出.
        3)遠(yuǎn)程進(jìn)程從套接口接收數(shù)據(jù),共收到本地進(jìn)程在1)和2)中發(fā)送的55字節(jié).
    另一重要性質(zhì):有序性
    SOCK_STREAM 套接口
        1)不保留消息邊界:接收端無法知道發(fā)送端發(fā)送數(shù)據(jù)時共執(zhí)行了幾次write
        2)保證接收數(shù)據(jù)字節(jié)與發(fā)送時順序一致
        3)保證寫入的數(shù)據(jù)在接收端被無錯接收
4.3.2 SOCK_DGRAM
    當(dāng)我們不需要數(shù)據(jù)傳輸?shù)慕^對有序性時和有需要數(shù)據(jù)傳輸?shù)目煽啃詴r,可以考慮使用SOCK_DGRAM.
    特性:
    1)分組發(fā)送后,可能無序的到達(dá)接收端。
    2)分組可以可能發(fā)生丟失。
    3)數(shù)據(jù)報分組有尺寸的大小限制,如果超出,可能會無法傳送。
    4)分組可以在不建立連接的情況下被發(fā)送到遠(yuǎn)程進(jìn)程,這就允許本地進(jìn)程每次將消息發(fā)送給不同IP地址上的同樣的端口。
4.3.3 SOCK_SEQPACKET
    本套接口對于X.25和AX.25協(xié)議非常重要,它與SOCK_STREAM的差別:SOCK_STERAM不保留消息邊界,而SOCK_SEQPACKET保留.
    特性:
    1)保留消息邊界
    2)數(shù)據(jù)字節(jié)的接收順序與發(fā)送順序一致
    3)保證發(fā)送數(shù)據(jù)字節(jié)被無錯地傳送到接收端
    4)數(shù)據(jù)是通過一對連接的套接口進(jìn)行傳送的
============================================
注意:不是每個協(xié)議族都可以使用所有的套接口類型,如:PF_INET協(xié)議族支持SOCK_STREAM類型,但不支持SOCK_SEQPACKET類型,對于PF_X25協(xié)議族則相反,支持SOCK_SEQPACKET類型,但不支持SOCK_STREAM類型
============================================
4.4 選擇協(xié)議
域(Domain) 套接口類型(socket type)    協(xié)議(Protocol)      描述(Description)
PF_LOCAL      SOCK_STREAM                0                   本地流套接口
PF_LOCAL      SOCK_DGRAM                 0                   本地數(shù)據(jù)報套接口
PF_INET       SOCK_STREAM                0或IPPROTO_TCP      TCP/IP流套接口
PF_INET       SOCK_DGRAM                 0或IPPROTO_UDP      UDP數(shù)據(jù)報套接口
4.6 linux支持的協(xié)議
socket()參數(shù)
域(Domain)    套接口類型(Socket Type)    描述
PF_LOCAL      SOCK_STREAM                本地主機(jī)上提供面向流的套接口.該服務(wù)是一各面向連接的可靠有序的服務(wù).注意:PF_UNIX=PF_LOCAL
PF_LOCAL      SOCK_DGRAM                 在本地主機(jī)上提供數(shù)據(jù)服務(wù).該服務(wù)是一種可靠的非連接的服務(wù),但在內(nèi)核緩沖耗盡時也可能會發(fā)生分組丟失
PF_INET       SOCK_STREAM                為面向Internet連接套接口提供流I/O服務(wù).這種組合表明所使用的是TCP/IP協(xié)議,因此是可靠,有序的
PF_INET       SOCK_DGRAM                 為面向Internet連接套接口提供數(shù)據(jù)報I/O服務(wù),這中組合表明所使用的是UDP協(xié)議,因此是不可靠的
PF_INET6      SOCK_STREAM                為面向IPv6連接套接口提供流I/O服務(wù),.這種組合表明所使用的是TCP/IP協(xié)議,因此是可靠,有序的
PF_INET6      SOCK_SEQPACKET             為面向IPv6連接套接口提供流I/O服務(wù),.這種組合表明所使用的是TCP/IP協(xié)議,因此是可靠,有序的,且保留了消息的邊界
PF_INET6      SOCK_DGRAM                 為面向IPv6連接套接口提供數(shù)據(jù)報I/O服務(wù),這中組合表明所使用的是UDP協(xié)議,因此是不可靠的
PF_X25        SOCK_DGRAM (????)         為X.25協(xié)議提供流I/O服務(wù),該服務(wù)是一種面向連接的服務(wù),是可靠的,有序的,且保留了消息邊界
PF_AX25       SOCK_STREAM                為AX.25協(xié)議提供流I/O服務(wù),該服務(wù)是一種面向連接的服務(wù),是可靠的,有序的,且保留了消息邊界
PF_AX25       SOCK_DGRAM                 為面向AX.25連接套接口提供數(shù)據(jù)報I/O服務(wù),是不可靠的
PF_APPLETALK SOCK_DGRAM (????)         為AppleTalk的套接口提供流I/O服務(wù),該服務(wù)是一種面向連接的服務(wù),是可靠的,有序的
PF_APPLETALK SOCK_STREAM                是一個擴(kuò)展
PF_ECONET     SOCK_DGRAM                 Acorn Econet和AUN協(xié)議的實現(xiàn)
PF_IPX        SOCK_STREAM                IPX協(xié)議,流套接口
PF_IPX        SOCK_DGRAM                 IPX協(xié)議,數(shù)據(jù)報套接口
PF_IPX        SOCK_SEQPACKET             IPX協(xié)議,有序分組套接口
PF_IRDA       SOCK_STREAM                支持IrDA子系統(tǒng),使用流套接口(紅外線通信)
PF_IRDA       SOCK_SEQPACKET             支持IrDA子系統(tǒng),使用保留消息邊界的流套接口(紅外線通信)
PF_NETROM     SOCK_SEQPACKET             業(yè)余無線電NetROM協(xié)議
PF_ROSE       SOCK_SEQPACKET             業(yè)余無線電X.25PLP協(xié)議



本文來自ChinaUnix博客,如果查看原文請點(diǎn):http://blog.chinaunix.net/u1/35045/showart_2015124.html
您需要登錄后才可以回帖 登錄 | 注冊

本版積分規(guī)則 發(fā)表回復(fù)

  

北京盛拓優(yōu)訊信息技術(shù)有限公司. 版權(quán)所有 京ICP備16024965號-6 北京市公安局海淀分局網(wǎng)監(jiān)中心備案編號:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年舉報專區(qū)
中國互聯(lián)網(wǎng)協(xié)會會員  聯(lián)系我們:huangweiwei@itpub.net
感謝所有關(guān)心和支持過ChinaUnix的朋友們 轉(zhuǎn)載本站內(nèi)容請注明原作者名及出處

清除 Cookies - ChinaUnix - Archiver - WAP - TOP