版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
socket通信過程及流程
卜?圖是基于TCP協(xié)議的客戶端/服務(wù)器程序的一般流程:
展務(wù)駕端應(yīng)用層
listenfd-sockets
分配-個(gè)文徉硒符
binddistenfd,聯(lián)弟等地址澆口)
辨定istenf曲海城
自存地址任意
listendistenfd,琳度)
使listenfd成為一個(gè)監(jiān)聽病述符
connfd-acceptdistenfd.客用出期口)
困爰等待客戶希f接
accept返回
分配斬的向S承。nnfdW戶襦通信
read(connfd.buf,size)"
阻塞等待客戶微據(jù)清浪
readj§0箱壞
處屏戶端話求多次
writetconnfd,but.size)
發(fā)送或據(jù)點(diǎn)M
read(connfd.buf.size)
閑兗等待客戶都據(jù)諾求
rea施回0
close(connfd)
服務(wù)器調(diào)用socket()、bind()、listen()完成初始化后,調(diào)用accept。阻塞等待,處于監(jiān)聽端口的狀態(tài),客
戶端調(diào)用socket。初始化后,調(diào)用connect。發(fā)出SYN段并阻塞等待服務(wù)器應(yīng)答,服務(wù)器應(yīng)答?個(gè)
SYN-ACK段,客戶端收到后從connect。返回,同時(shí)應(yīng)答一個(gè)ACK段,服務(wù)器收到后從accept。返回。
數(shù)據(jù)傳輸?shù)倪^程:
建立連接后,TCP協(xié)議提供全雙工的通信服務(wù),但是?般的客戶端/服務(wù)腓程序的流程是由客戶端主動(dòng)
發(fā)起請求,服務(wù)器被動(dòng)處理請求,一問一答的方式。因此服務(wù)器從accept。返回后立刻調(diào)用read。,
讀socket就像讀管道一樣,如果沒有數(shù)據(jù)到達(dá)就阻塞等待,這時(shí)客戶端調(diào)用write。發(fā)送請求給服務(wù)器,
服務(wù)器收到后從read。返回,對客戶端的請求進(jìn)行處理,在此期間客戶端調(diào)用read()阻塞等待服務(wù)器
的應(yīng)答,服務(wù)器調(diào)用write。將處理結(jié)果發(fā)回給客戶端,再次調(diào)用read。阻塞等待下一條請求,客戶端
收到后從read。返回,發(fā)送下一條請求,如此循環(huán)下去。
如果客戶端沒有更多的請求了,就調(diào)用close。關(guān)閉連接,就像寫端關(guān)閉的管道一樣,服務(wù)器的read。
返回0,這樣服務(wù)器就知道客戶端關(guān)閉了連接,也調(diào)用close。關(guān)閉連接。注意,任何一方調(diào)用close。
后,連接的兩個(gè)傳輸方向都關(guān)閉,不能再發(fā)送數(shù)據(jù)了。如果功.調(diào)用shutdown。則連接處于半關(guān)閉狀
態(tài),仍可接收對方發(fā)來的數(shù)據(jù)。
在學(xué)習(xí)socketAPI時(shí)要注意應(yīng)用程序和TCP協(xié)議層是如何交互的:*應(yīng)用程序調(diào)用某個(gè)socket函數(shù)
時(shí)TCP協(xié)議層完成什么動(dòng)作,比如調(diào)用connect。會(huì)發(fā)出SYN段?應(yīng)用程序如何知道TCP協(xié)議層的
狀態(tài)變化,比如從某個(gè)阻塞的socket函數(shù)返回就表明TCP協(xié)議收到了某些段,再比如read。如回0
就表明收到了FIN段
看圖所示的-socket通信過程
server一方的socketclient一方的socket
圖12.9socket的通信過程
1.建立套接字
在sys/socket.h中。
intsocket(intfamily,inttype,intprotocol);
socket。打開一個(gè)網(wǎng)絡(luò)通訊端口,如果成功的話,就像open。一樣返回一個(gè)文件描述符,應(yīng)用程序可
以像讀寫文件一樣用read/write在網(wǎng)絡(luò)上收發(fā)數(shù)據(jù),如果socket。調(diào)用出錯(cuò)則返回-1“對于IPv4,
family參數(shù)指定為AFJNEK對于TCP協(xié)議,type參數(shù)指定為SOCK_STREAM,表示面向流的傳輸
協(xié)議。如果是UDP協(xié)議,則type參數(shù)指定為SOCK_DGRAM,表示面向數(shù)據(jù)報(bào)的傳輸協(xié)議,protocol
參數(shù)的介紹從略,指定為0即可。
Linux在利用socket。系統(tǒng)調(diào)用建立新的套接字時(shí),需要傳遞套接字的地址族標(biāo)識(shí)符、套接字類型以
及協(xié)議,其函數(shù)定義于net/socket.c中:
asmlinkagelongsys_socket(intfamily,inttype,intprotocol1
intretval;
structsocket*sock;
retval=sock_create(family,type,protocol,&sock);
if(retval<0)
gotoout;
retval=sock_map_fd(sock);
if(retval<0)
gotoout_release;
out:
/.l.ma.b.alread.anothe.descripto.8.Nblem.*/
returnretval;
outrelease:
sock_release(sock);
returnretval;
}
實(shí)際上,套接字對于用戶程序而言就是特殊的已打開的文件。內(nèi)核中為套接字定義了一種特殊的文
件類型,形成一種特殊的文件系統(tǒng)sockfs,其定義于net/socket.c:
staticstructvfsmount*sock_mnt;
staticDECLARE_FSTYPE(sock_fs_type,"sockfs",sockfs_read_super,FS_NOMOUNT);
在系統(tǒng)初始化時(shí),要通過kern_mount()安裝這個(gè)文件系統(tǒng)。安裝時(shí)有個(gè)作為連接件的vfsmount數(shù)
據(jù)結(jié)構(gòu),這個(gè)結(jié)構(gòu)的地址就保存在一個(gè)全局的指針sock_mnt中。所謂創(chuàng)建一個(gè)套接字,就是在sockfs
文件系統(tǒng)中創(chuàng)建一個(gè)特殊文件,或者說一個(gè)節(jié)點(diǎn),并建立起為實(shí)現(xiàn)套接字功能所需的一整套數(shù)據(jù)結(jié)構(gòu)。
所以,函數(shù)sock_create()首先是建立一個(gè)socket數(shù)據(jù)結(jié)構(gòu),然后將其“映射”到一個(gè)已打開的文件
中,進(jìn)行socket結(jié)構(gòu)和sock結(jié)構(gòu)的分配和初始化。
新創(chuàng)建的BSDsocket數(shù)據(jù)結(jié)構(gòu)包含有指向地址族專有的套接字例程的指針,這一指針實(shí)際就是
proto_ops數(shù)據(jù)結(jié)構(gòu)的地址。
BSD套接字的套接字類型設(shè)置為所請求的SOCK_STREAM或SOCK_DGRAM等。然后,內(nèi)核利
用proto_ops數(shù)據(jù)結(jié)構(gòu)中的信息調(diào)用地址族專有的創(chuàng)建例程。
之后,內(nèi)核從當(dāng)前進(jìn)程的fd向量中分配空閑的文件描述符,該描述符指向的file數(shù)據(jù)結(jié)構(gòu)被初始化。
初始化過程包括將文件操作集指針指向由BSD套接字接口支持的BSD文件操作集。所有隨后的套
接字(文件)操作都將定向到該套接字接口,而套接字接口則會(huì)進(jìn)一步調(diào)用地址族的操作例程,從而
將操作傳遞到底層地址族,如圖12.10所示。
flles.slrucl
closeonexec
openA
BSD套鞭子
文件,作票
bt?kioc"
re?dclott
writefMync
faodeselect
fHMioa
SOCK.STREAM地址嫉
SOCKSTREAM
protocol
實(shí)際上,socket結(jié)構(gòu)與sock結(jié)構(gòu)是同一事物的兩個(gè)方面。如果說socket結(jié)構(gòu)是面向進(jìn)程和系統(tǒng)調(diào)用
界面的,那么sock結(jié)構(gòu)就是面向底層驅(qū)動(dòng)程序的。可是,為什么不把這兩個(gè)數(shù)據(jù)結(jié)構(gòu)合并成?個(gè)呢?
我們說套接字是一種特殊的文件系統(tǒng),Wilt,inode結(jié)構(gòu)內(nèi)部的union的一個(gè)成分就用作socket結(jié)構(gòu),
其定義如下:
structinode
union{
structsocketsocketj;
)
由于套接字操作的特殊性,這個(gè)結(jié)構(gòu)中需要大量的結(jié)構(gòu)成分??墒?,如果把這些結(jié)構(gòu)成分全都放在
socket結(jié)構(gòu)中,則inode結(jié)構(gòu)中的這個(gè)union就會(huì)變得很大,從而inode結(jié)構(gòu)也會(huì)變得很大,而對于
其他文件系統(tǒng),這個(gè)union成分并不需要那么龐大。因此,就把套接字所需的這些結(jié)構(gòu)成分拆成兩部
分,把與文件系統(tǒng)關(guān)系比較密切的那一部分放在socket結(jié)構(gòu)中,把與通信關(guān)系比較密切的那一部分則
單獨(dú)組成?個(gè)數(shù)據(jù)結(jié)構(gòu),即sock結(jié)構(gòu)。由于這兩部分?jǐn)?shù)據(jù)在邏輯上本來就是?體的,所以要通過指針
互相指向?qū)Ψ?,形成一對一的關(guān)系。
2.在INETBSD套接字上綁定(bind)地址
為了監(jiān)聽傳入的Internet連接請求,每個(gè)服務(wù)器都需要建立一個(gè)INETRSD套接
字,并且將自己的地址綁定到該套接字。綁定操作主要在INET套接字層中進(jìn)行,
還需要底層TCP層和IP層的某些支持。將地址綁定到某個(gè)套接字上之后,該套
接字就不能用來進(jìn)行任何其他的通訊,因此,該socket數(shù)據(jù)結(jié)構(gòu)的狀態(tài)必須為
TCP_CLOSE。傳遞到J綁定操作的sockaddr數(shù)據(jù)結(jié)構(gòu)中包含要綁定的IP地址,以
及一個(gè)可選的端口地址。通常而言,要綁定的地址應(yīng)該是賦予某個(gè)網(wǎng)絡(luò)設(shè)備的IP
地址,而該網(wǎng)絡(luò)設(shè)備應(yīng)該支持INET地址族,并且該設(shè)備是可用的。利用ifconfig
命令可查看當(dāng)前活動(dòng)的網(wǎng)絡(luò)接口。被綁定的IP地址保存在sock數(shù)據(jù)結(jié)構(gòu)的
rcv_saddr和saddr域中,這兩個(gè)域分別用丁哈希直找和發(fā)送用的IP地址。端口
地址是可選的,如果沒有指定,底層的支持網(wǎng)絡(luò)會(huì)選擇一個(gè)空閑的端口。
intbind(intsockfd,conststructsockaddr*myaddrzsocklent
addrlen);
服務(wù)器程序所監(jiān)聽的網(wǎng)絡(luò)地址和端口號通常是固定不變的,客戶端程序得知服務(wù)器程序的地址和端
口號后就可以向服務(wù)器發(fā)起連接,因此服務(wù)器需要調(diào)用bind綁定一個(gè)固定的網(wǎng)絡(luò)地址和端口號。bind。
成功返回0,失敗返回7。
bind。的作用是將參數(shù)sockfd和myaddr綁定在一起,使sockfd這個(gè)用于網(wǎng)絡(luò)通訊
的文件描述符監(jiān)聽myaddr所描述的地址和端口號。前面講過,structsockaddr*是
一個(gè)通用指針類型,myaddr參數(shù)實(shí)際上可以接受多種協(xié)議的sockaddr結(jié)構(gòu)體,而它
們的長度各不相同,所以需要第三個(gè)參數(shù)addrlen指定結(jié)構(gòu)體的長度。我們的程序中
對myaddr參數(shù)是這樣初始化的:
bzero(&servaddr,sizeof(servaddr));
servaddr.sin_family=AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(SERV_P0RT);
首先將整個(gè)結(jié)構(gòu)體清零,然后設(shè)置地址類型為AF_INET,網(wǎng)絡(luò)地址為INADDR_ANY,這個(gè)宏表示本
地的任意IP地址,因?yàn)榉?wù)器可能有多個(gè)網(wǎng)卡,每個(gè)網(wǎng)卡也可能綁定多個(gè)IP地址,這樣設(shè)置可以在
所有的IP地址上監(jiān)聽,直到與某個(gè)客戶端建立了連接時(shí)才確定下來到底用哪個(gè)IP地址,端口號為
SERV_PORT,我們定義為8000。
當(dāng)?shù)讓泳W(wǎng)絡(luò)設(shè)備接受到數(shù)據(jù)包時(shí),它必須將數(shù)據(jù)包傳遞到正確的INET和BSD套接字以便進(jìn)吁處
理,因此,TCP維護(hù)多個(gè)哈希表,用來查找傳入IP消息的地址,并將它們定向到正確的socket/sock
對。TCP并不在綁定過程中將綁定的sock數(shù)據(jù)結(jié)構(gòu)添加到哈希表中,在這一過程中,它僅僅判斷所
請求的端口號當(dāng)前是否正在使用。在監(jiān)聽操作中,該sock結(jié)構(gòu)才被添加到TCP的哈希表中。
3.在INETBSD套接字上建立連接(connect)
創(chuàng)建一個(gè)套接字之后,該套接字不僅可以用于監(jiān)聽入站的連接請求,也可以用于
建立出站的連接請求。不論怎樣都涉及到一個(gè)重要的過程:建立兩個(gè)應(yīng)用程序之間
的虛擬電路。出站連接只能建立在處于正確狀態(tài)的INETBSD套接字上,因此,不
能建立于已建立連接的套接字,也不能建立于用于監(jiān)聽入站連接的套接字。也就是
說,該BSDsocket數(shù)據(jù)結(jié)構(gòu)的狀態(tài)必須為SS_UNC0NNECTEDo
在建立連接過程中,雙方TCP要進(jìn)行三次“握手”,具體過程在本章第二節(jié)一
網(wǎng)絡(luò)協(xié)議一文中有詳細(xì)介紹。如果TCPsock正在等待傳入消息,則該sock結(jié)構(gòu)
添加到tcp_listening_hash表中,這樣,傳入的TCP消息就可以定向到該sock
數(shù)據(jù)結(jié)構(gòu)。
由于客戶端不需要固定的端口號,因此不必調(diào)用bind。,客戶端的端口號由內(nèi)核自
動(dòng)分配。注意,客戶端不是不允許調(diào)用bind。,只是沒有必要調(diào)用bind。固定一個(gè)端
口號,服務(wù)器也不是必須調(diào)用bind(),但如果服務(wù)器不調(diào)用bind(),內(nèi)核會(huì)自動(dòng)給服
務(wù)器分配監(jiān)聽端口,每次啟動(dòng)服務(wù)器時(shí)端口號都不一樣,客戶端要連接服務(wù)器就會(huì)
遇到麻煩。
intconnect(intsockfd,conststructsockaddr*servaddr,
socklentaddrlen);
客戶端需要調(diào)用connect。連接服務(wù)器,connect和bind的參數(shù)形式一致,區(qū)別在于bind的參數(shù)是自
己的地址,而connect的參數(shù)是對方的地址。connect。成功返回0,出錯(cuò)返回-1。
4.監(jiān)聽(listen)INETBSD套接字
intlisten(intsockfd,intbacklog);
典型的服務(wù)器程序可以同時(shí)服務(wù)于多個(gè)客戶端,當(dāng)有客戶端發(fā)起連接時(shí),服務(wù)器調(diào)用的accept。返回
并接受這個(gè)連接,如果有大量的客戶端發(fā)起連接而服務(wù)器來不及處理,尚未accept的客戶端就處于
連接等待狀態(tài),listen。聲明sockfd處于監(jiān)聽狀態(tài),并且最多允許有backlog個(gè)客戶端處于連接待狀態(tài),
如果接收到更多的連接請求就忽略。listen。成功返回0,失敗返回-1。
當(dāng)某個(gè)套接字被綁定了地址之后,該套接字就可以用來監(jiān)聽專屬于?該綁定地址的傳入連接。網(wǎng)絡(luò)應(yīng)
用程序也可以在未綁定地址之前監(jiān)聽套接字,這肘,INET套接字層將利用空閑的端口編號并自動(dòng)綁
定到該套接字。套接字的監(jiān)聽函數(shù)將socket的狀態(tài)改變?yōu)門CP_LISTENo
當(dāng)接收到某個(gè)傳入的TCP連接請求時(shí),TCP建匯?個(gè)新的sock數(shù)據(jù)結(jié)構(gòu)來描述該連接。當(dāng)該連接
最終被接受時(shí),新的sock數(shù)據(jù)結(jié)構(gòu)將變成該TCP連接的內(nèi)核bottom_half部分,這時(shí),它要克隆
包含連接請求的傳入sk_buff中的信息,并在監(jiān)聽sock數(shù)據(jù)結(jié)構(gòu)的receive_queue隊(duì)列中將克隆
的信息排隊(duì)??寺〉膕k_buff中包含有指向新sock數(shù)據(jù)結(jié)構(gòu)的指針。
5.接受連接請求(accept)
接受操作在監(jiān)聽套接字上進(jìn)行,從監(jiān)聽socket中克隆一個(gè)新的socket數(shù)據(jù)結(jié)構(gòu)。
其過程如下:接受操作首先傳遞到支持協(xié)議層,即
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(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ǔ)空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 生物信息學(xué)分析IBD癌變的關(guān)鍵調(diào)控基因
- 保險(xiǎn)行業(yè)數(shù)據(jù)分析師的答案解析
- 物業(yè)管理師國家職業(yè)資格考試復(fù)習(xí)含答案
- 深度解析(2026)《GBT 19448.3-2004圓柱柄刀夾 第3部分裝徑向矩形車刀的B型刀夾》
- 辦公室文員工作考核標(biāo)準(zhǔn)及辦法
- 瓣膜介入器械的麻醉配合策略
- 環(huán)保組織招聘環(huán)保項(xiàng)目活動(dòng)策劃與執(zhí)行專員面試題及答案
- 網(wǎng)絡(luò)安全專家面試題及攻防實(shí)戰(zhàn)案例含答案
- 剪床項(xiàng)目可行性分析報(bào)告范文(總投資7000萬元)
- 寬容和感恩的培訓(xùn)
- 廣東省汕頭市金平區(qū)2024-2025學(xué)年七年級上學(xué)期期末考試數(shù)學(xué)試題
- 過敏性休克的搶救流程
- 常用機(jī)床電氣檢修課件 課題十一 T612 型臥式鏜床電氣檢修
- 全國人大機(jī)關(guān)直屬事業(yè)單位2026年度公開招聘工作人員考試模擬卷帶答案解析
- 云肩非遺模板
- 頭頸部腫瘤介紹
- 安全監(jiān)理工作總程序
- 2026年中國宏觀經(jīng)濟(jì)展望分析報(bào)告:底部夯實(shí)亮點(diǎn)引領(lǐng)未來方向
- 2025年新型健康飲品研發(fā)可行性研究報(bào)告及總結(jié)分析
- 竣工決算業(yè)務(wù)合同范本
評論
0/150
提交評論