溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Socket調(diào)用過(guò)程是怎樣的

發(fā)布時(shí)間:2021-12-21 14:18:11 來(lái)源:億速云 閱讀:157 作者:iii 欄目:大數(shù)據(jù)

本篇內(nèi)容介紹了“Socket調(diào)用過(guò)程是怎樣的”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

Socket由來(lái)

在學(xué)習(xí)一個(gè)新知識(shí)之前,要去想它為什么會(huì)出現(xiàn),它的出現(xiàn)解決了什么問(wèn)題.這樣印象才會(huì)深刻一些.

在同一個(gè)主機(jī)下,兩個(gè)進(jìn)程間的通訊是很容易,直接把各種通訊細(xì)節(jié)交給操作系統(tǒng)去做就 OK 了.但是如果兩個(gè)進(jìn)程是處于不同主機(jī)下呢?該如何進(jìn)行通訊呢?而且在實(shí)際的應(yīng)用場(chǎng)景中,是很復(fù)雜的,有的使用 TCP 協(xié)議,有的使用 UDP 協(xié)議,那么當(dāng)我們使用不同的協(xié)議進(jìn)行通信時(shí),是不是就要使用不同的接口?同時(shí)還要處理不同協(xié)議的各種通訊細(xì)節(jié),這樣一來(lái),是不是就增加了開(kāi)發(fā)的難度,同時(shí)軟件不容易進(jìn)行擴(kuò)展.

編程思想之一就是「面向?qū)ο蟆?同樣,在遇到這種問(wèn)題時(shí),我能不能把不同協(xié)議的通信細(xì)節(jié)抽出來(lái),這樣程序員在使用的時(shí)候,直接調(diào)用,就不需要再關(guān)注協(xié)議本身了.而這就是 Socket 的由來(lái).

它提供接口,來(lái)進(jìn)行互聯(lián)的不同主機(jī)之間的進(jìn)程通信.你想要讓不同主機(jī)之間通信? OK ,你直接調(diào)用我就行,至于我怎么實(shí)現(xiàn),程序員不需要 care .

在上面的基礎(chǔ)上,我們能夠達(dá)成一個(gè)共識(shí):如果一個(gè)應(yīng)用,需要在客戶端和服務(wù)端之間進(jìn)行通信,那就需要?jiǎng)?chuàng)建一個(gè) Socket 實(shí)例. 那么問(wèn)題來(lái)了,我如何使用?

Socket 進(jìn)行的是端到端的通信,中間經(jīng)過(guò)多少局域網(wǎng),路過(guò)多少路由器,我是不清晰的,所以能夠設(shè)置的參數(shù),也只是端到端協(xié)議之上的網(wǎng)絡(luò)層和傳輸層. 在網(wǎng)絡(luò)層, Socket 函數(shù)需要指定使用到的協(xié)議到底是 IPv4 還是 IPv6 ,分別對(duì)應(yīng)設(shè)置為 AF_INET 和 AF_INET6 .此外,還需要說(shuō)明你是使用 TCP 協(xié)議,還是 UDP 協(xié)議. TCP 協(xié)議是基于數(shù)據(jù)流的,所以設(shè)置為 SOCK_STREAM , UDP 是基于數(shù)據(jù)報(bào)的,因而設(shè)置為 SOCK_DGRAM .

 

Socket調(diào)用過(guò)程

客戶端和服務(wù)端創(chuàng)建 Socket 之后, TCP 的服務(wù)端要先監(jiān)聽(tīng)一個(gè)端口,一般是先調(diào)用 bind 函數(shù),給這個(gè) Socket 賦予一個(gè) IP 地址和端口.為什么需要 IP 地址呢?有時(shí)候一臺(tái)機(jī)器會(huì)有多個(gè)網(wǎng)卡,相應(yīng)的就會(huì)有多個(gè) IP 地址,可以選擇監(jiān)聽(tīng)所有的網(wǎng)卡,也可以選擇監(jiān)聽(tīng)一個(gè)網(wǎng)卡,這樣只有發(fā)給這個(gè)網(wǎng)卡的包,才會(huì)給你.那我為什么還需要端口呢?你要知道,你寫(xiě)的是一個(gè)應(yīng)用程序,當(dāng)一個(gè)網(wǎng)絡(luò)包來(lái)的時(shí)候,內(nèi)核是需要通過(guò) TCP 頭里面的這個(gè)端口,來(lái)定位到你這個(gè)應(yīng)用程序的.

此時(shí),當(dāng)服務(wù)端有了 IP 和端口號(hào),就可以調(diào)用 listen 函數(shù)進(jìn)行監(jiān)聽(tīng).在 TCP 的狀態(tài)圖中,有一個(gè) listen 狀態(tài),當(dāng)調(diào)用這個(gè)函數(shù)之后,服務(wù)端就進(jìn)入了這個(gè)狀態(tài),這個(gè)時(shí)候客戶端那邊就可以發(fā)起連接了.

在內(nèi)核中,為每個(gè) Socket 維護(hù)了兩個(gè)隊(duì)列,一個(gè)是已經(jīng)建立了連接的隊(duì)列,說(shuō)明此時(shí)三次握手已經(jīng)完畢,處于 established 狀態(tài);一個(gè)是還沒(méi)有完全建立連接的隊(duì)列,也就是說(shuō)這個(gè)時(shí)候三次握手還沒(méi)完成,處于 syn_rcvd 的狀態(tài).

接下來(lái),服務(wù)端調(diào)用 accept 函數(shù),拿出一個(gè)已經(jīng)完成的連接進(jìn)行處理.如果客戶端還沒(méi)有完全建立連接,沒(méi)別的辦法,就等著咯.

在服務(wù)端等待的時(shí)候,客戶端可以通過(guò) connect 函數(shù)發(fā)起連接.現(xiàn)在參數(shù)中指明要連接的 IP 地址和端口號(hào),然后開(kāi)始發(fā)起三次握手.內(nèi)核會(huì)給客戶端分配一個(gè)臨時(shí)的端口,一旦握手成功,服務(wù)端的 accept 就會(huì)返回另一個(gè) Socket .

注意一下,在這里有一個(gè)經(jīng)??疾斓闹R(shí)點(diǎn),就是監(jiān)聽(tīng)的 Socket 和真正用來(lái)傳數(shù)據(jù)的 Socket 是兩個(gè),一個(gè)叫做「監(jiān)聽(tīng) Socket 」,一個(gè)叫做「已連接 Socket 」.

連接建立成功之后,雙方就開(kāi)始通過(guò) read 和 write 函數(shù)來(lái)讀寫(xiě)數(shù)據(jù),就像往一個(gè)文件流里面寫(xiě)東西一樣.之所以把 TCP 的 Socket 描述成一個(gè)文件流,是因?yàn)?Socket 在 Linux 中就是以文件的形式存在的.

在內(nèi)核中, Socket 是一個(gè)文件,那對(duì)應(yīng)就有文件描述符.每一個(gè)進(jìn)程都有一個(gè)數(shù)據(jù)結(jié)構(gòu) task_struct ,里面指向一個(gè)文件描述符數(shù)組,來(lái)列出這個(gè)進(jìn)程打開(kāi)的所有文件的文件描述符.文件描述符是一個(gè)整數(shù),是這個(gè)數(shù)組的下標(biāo).

這個(gè)數(shù)組中的內(nèi)容是一個(gè)指針,指向內(nèi)核中所有打開(kāi)的文件的列表.既然是一個(gè)文件,就會(huì)有一個(gè) inode ,只不過(guò) Socket 對(duì)應(yīng)的 inode 不像真正的文件系統(tǒng)一樣,保存在硬盤上,而是在內(nèi)存中.在這個(gè) inode 中,指向了 Socket 在內(nèi)核中的 Socket 結(jié)構(gòu).

在這個(gè)結(jié)構(gòu)中,主要的是兩個(gè)隊(duì)列,一個(gè)是發(fā)送隊(duì)列,一個(gè)是接收隊(duì)列.在這兩個(gè)隊(duì)列里面保存的是一個(gè)緩存 sk_buff .這個(gè)緩存中能夠看到完整的包的結(jié)構(gòu).

以上,就是基于 TCP 協(xié)議的 Socket 程序函數(shù)調(diào)用過(guò)程的一個(gè)描述

接下來(lái)說(shuō)說(shuō)基于 UDP 協(xié)議的 Socket 程序函數(shù)調(diào)用過(guò)程.

基于 UDP 協(xié)議的 Socket 程序函數(shù)調(diào)用過(guò)程 對(duì)于 UDP 來(lái)說(shuō),和 TCP 還是有些不一樣的.首先, UDP 是沒(méi)有連接的,也就不需要三次握手,也不需要調(diào)用 listen 和 connect ,但是 UDP 的交互仍然需要 IP 和端口號(hào),那就需要 bind .

UDP 是沒(méi)有維護(hù)連接狀態(tài)的,也就不需要對(duì)每對(duì)連接建立一組 Socket ,而是只要有一個(gè) Socket 就可以和多個(gè)客戶端通信.也是因?yàn)闆](méi)有連接狀態(tài),所以每次通信的時(shí)候,都調(diào)用 sendto 和 recvfrom ,這樣才可以傳入 IP 地址和端口.

“Socket調(diào)用過(guò)程是怎樣的”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI