最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會員登陸 & 注冊

socket套接字及緩沖區(qū)詳解(一篇搞定~)

2022-09-23 14:50 作者:補給站Linux內(nèi)核  | 我要投稿

文章目錄

一、域(domain) 二、類型(type) 三、協(xié)議(protocol) 四、socket緩沖區(qū)以及阻塞模式 1、緩沖區(qū)簡介 2、使用write()/send()發(fā)送數(shù)據(jù) 3、使用read()/recv()讀取數(shù)據(jù) 4、系統(tǒng)調(diào)用read()的返回錯誤場景 五、面試題--->TCP服務(wù)端一直sleep,客戶端發(fā)送數(shù)據(jù)問題 1、TCP發(fā)送數(shù)據(jù)的過程 2、阻塞方式的情況 3、非阻塞方式的情況 ?套接字是一種通信機制(通信的兩方的一種約定),憑借這種機制,不同主機之間的進程可以進行通信。我們可以用套接字中的相關(guān)函數(shù)來完成通信過程。

?套接字的特性有三個屬性確定,它們是:域(domain),類型(type),和協(xié)議(protocol)。

一、域(domain)

?域指定套接字通信中使用的網(wǎng)絡(luò)介質(zhì)。最常見的套接字域是 AF_INET(IPv4)或者AF_INET6(IPV6),它是指 Internet 網(wǎng)絡(luò),許多 Linux 局域網(wǎng)使用的都是該網(wǎng)絡(luò),當然,因特網(wǎng)自身用的也是它。

二、類型(type)

流套接字(SOCK_STREAM):

?流套接字用于提供面向連接、可靠的數(shù)據(jù)傳輸服務(wù)。該服務(wù)將保證數(shù)據(jù)能夠?qū)崿F(xiàn)無差錯、無重復發(fā)送,并按順序接收。流套接字之所以能夠?qū)崿F(xiàn)可靠的數(shù)據(jù)服務(wù),原因在于其使用了傳輸控制協(xié)議,即TCP(The Transmission Control Protocol)協(xié)議。

數(shù)據(jù)報套接字(SOCK_DGRAM):

?數(shù)據(jù)報套接字提供了一種無連接的服務(wù)。該服務(wù)并不能保證數(shù)據(jù)傳輸?shù)目煽啃?,?shù)據(jù)有可能在傳輸過程中丟失或出現(xiàn)數(shù)據(jù)重復,且無法保證順序地接收到數(shù)據(jù)。數(shù)據(jù)報套接字使用UDP(User Datagram Protocol)協(xié)議進行數(shù)據(jù)的傳輸。由于數(shù)據(jù)報套接字不能保證數(shù)據(jù)傳輸?shù)目煽啃?,對于有可能出現(xiàn)的數(shù)據(jù)丟失情況,需要在程序中做相應(yīng)的處理。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個人覺得比較好的學習書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實戰(zhàn)項目及代碼)??

原始套接字(SOCK_RAW):

?原始套接字與標準套接字(標準套接字指的是前面介紹的流套接字和數(shù)據(jù)報套接字)的區(qū)別在于:原始套接字可以讀寫內(nèi)核沒有處理的IP數(shù)據(jù)包,而流套接字只能讀取TCP協(xié)議的數(shù)據(jù),數(shù)據(jù)報套接字只能讀取UDP協(xié)議的數(shù)據(jù)。因此,如果要訪問其他協(xié)議發(fā)送數(shù)據(jù)必須使用原始套接字。

三、協(xié)議(protocol)

0: ? 使用默認協(xié)議;

IPPROTO_TCP; ? 使用TCP協(xié)議;

IPPROTO_UDP; ? 使用UDP協(xié)議;

四、socket緩沖區(qū)以及阻塞模式

1、緩沖區(qū)簡介

?每個 socket 被創(chuàng)建后,都會分配兩個緩沖區(qū),輸入緩沖區(qū)和輸出緩沖區(qū)。

?write()/send() 并不立即向網(wǎng)絡(luò)中傳輸數(shù)據(jù),而是先將數(shù)據(jù)寫入緩沖區(qū)中,再由TCP協(xié)議將數(shù)據(jù)從緩沖區(qū)發(fā)送到目標機器。一旦將數(shù)據(jù)寫入到緩沖區(qū),函數(shù)就可以成功返回,不管它們有沒有到達目標機器,也不管它們何時被發(fā)送到網(wǎng)絡(luò),這些都是TCP協(xié)議負責的事情。 ?read()/recv() 函數(shù)也是如此,也從輸入緩沖區(qū)中讀取數(shù)據(jù),而不是直接從網(wǎng)絡(luò)中讀取。


I/O緩沖區(qū)在每個TCP套接字中單獨存在; I/O緩沖區(qū)在創(chuàng)建套接字時自動生成; 即使關(guān)閉套接字也會繼續(xù)傳送輸出緩沖區(qū)中遺留的數(shù)據(jù); 關(guān)閉套接字將丟失輸入緩沖區(qū)中的數(shù)據(jù)。



2、使用write()/send()發(fā)送數(shù)據(jù)

【阻塞模式下】:

首先會檢查緩沖區(qū),如果緩沖區(qū)的可用空間長度小于要發(fā)送的數(shù)據(jù),那么 write()/send() 會被阻塞(暫停執(zhí)行),直到緩沖區(qū)中的數(shù)據(jù)被發(fā)送到目標機器,騰出足夠的空間,才喚醒 write()/send() 函數(shù)繼續(xù)寫入數(shù)據(jù);

如果TCP協(xié)議正在向網(wǎng)絡(luò)發(fā)送數(shù)據(jù),那么輸出緩沖區(qū)會被鎖定,不允許寫入,write()/send() 也會被阻塞,直到數(shù)據(jù)發(fā)送完畢緩沖區(qū)解鎖,write()/send() 才會被喚醒。如果TCP協(xié)議正在向網(wǎng)絡(luò)發(fā)送數(shù)據(jù),那么輸出緩沖區(qū)會被鎖定,不允許寫入,write()/send() 也會被阻塞,直到數(shù)據(jù)發(fā)送完畢緩沖區(qū)解鎖,write()/send() 才會被喚醒;

如果要寫入的數(shù)據(jù)大于緩沖區(qū)的最大長度,那么將分批寫入。如果要寫入的數(shù)據(jù)大于緩沖區(qū)的最大長度,那么將分批寫入;直到所有數(shù)據(jù)被寫入緩沖區(qū) write()/send() 才能返回。直到所有數(shù)據(jù)被寫入緩沖區(qū) write()/send() 才能返回。

send()函數(shù)默認情況下會使用Nagle算法。Nagle算法通過將未確認的數(shù)據(jù)存入緩沖區(qū)直到積攢到一定數(shù)量一起發(fā)送的方法,來降低主機發(fā)送零碎小數(shù)據(jù)包的數(shù)目。所以假設(shè)send()函數(shù)發(fā)送數(shù)據(jù)過快的話,該算法會將一些數(shù)據(jù)打包后統(tǒng)一發(fā)出去。通過setsockopt()的TCP_NODELAY選項來禁用Nagle算法。

【非阻塞模式下】:

send()函數(shù)的過程僅僅是將數(shù)據(jù)拷貝到協(xié)議棧的緩沖區(qū)而已,如果緩沖區(qū)可用空間不夠,則盡可能拷貝,返回成功拷貝的大小;如果緩存區(qū)可用空間為0,則返回-1,同時設(shè)置errno為EAGAIN。

3、使用read()/recv()讀取數(shù)據(jù)

【阻塞模式下】:

首先會檢查緩沖區(qū),如果緩沖區(qū)中有數(shù)據(jù),那么就讀取,否則函數(shù)會被阻塞,直到網(wǎng)絡(luò)上有數(shù)據(jù)到來;

如果要讀取的數(shù)據(jù)長度小于緩沖區(qū)中的數(shù)據(jù)長度,那么就不能一次性將緩沖區(qū)中的所有數(shù)據(jù)讀出,剩余數(shù)據(jù)將不斷積壓,直到讀取到數(shù)據(jù)后 read()/recv() 函數(shù)才會返回,否則就一直被阻塞。

【非阻塞模式下】:

接收數(shù)據(jù)時perror時常遇到“Resource temporarilyunavailable”的提示,errno代碼為11(EAGAIN)。這表明你在非阻塞模式下調(diào)用了阻塞操作,在該操作沒有完成就返回這個錯誤,這個錯誤不會破壞socket的同步,繼續(xù)循環(huán)接著recv就可以。

4、系統(tǒng)調(diào)用read()的返回錯誤場景

EINTR:在讀取到數(shù)據(jù)以前調(diào)用被信號所中斷。

EAGAIN:使用 O_NONBLOCK 標志指定了非阻塞式輸入輸出,但當前沒有數(shù)據(jù)可讀或者使用了阻塞操作。

EIO:輸入輸出錯誤.可能是正處于后臺進程組進程試圖讀取其控制終端,但讀操作無效,或者被信號SIGTTIN所阻塞,或者其進程組是孤兒進程組.也可能執(zhí)行的是讀磁盤或者磁帶機這樣的底層輸入輸出錯誤。

EISDIR:fd 指向一個目錄。

EBADF:fd 不是一個合法的文件描述符,或者不是為讀操作而打開。

EINVAL:fd 所連接的對象不可讀。

EFAULT:buf 超出用戶可訪問的地址空間。

EWOULDBLOCK:用于非阻塞模式,表示不需要重新讀或者寫。

五、面試題—>TCP服務(wù)端一直sleep,客戶端發(fā)送數(shù)據(jù)問題

1、TCP發(fā)送數(shù)據(jù)的過程

?TCP發(fā)送數(shù)據(jù)的大體過程:首先,TCP是有鏈接的可靠傳輸協(xié)議,所謂可靠也就是說保證客戶端發(fā)送的數(shù)據(jù)服務(wù)端都能夠收到,并且是按序收到。那么對于上面的問題就不可能存在數(shù)據(jù)的丟棄。那么客戶端一直發(fā)送數(shù)據(jù)越來越多怎么辦?下面我們分析一下TCP的傳輸過程。

  1. 數(shù)據(jù)首先由應(yīng)用程序緩沖區(qū)復制到發(fā)送端的輸出緩沖區(qū)(位于內(nèi)核),注意這個過程是用類似write功能的函數(shù)完成的。有的人通??吹絯rite成功就以為數(shù)據(jù)發(fā)送到了對端主機,其實這是錯誤的,write成功僅僅表示數(shù)據(jù)成功的由應(yīng)用進程緩沖區(qū)復制到了輸出緩沖區(qū)。

  2. 然后內(nèi)核協(xié)議棧將輸出緩沖區(qū)中的數(shù)據(jù)發(fā)送到對端主機,注意這個過程不受應(yīng)用程序控制,而是發(fā)送端內(nèi)核協(xié)議棧完成,其中包括使用滑動窗口、擁塞控制等功能。

  3. 數(shù)據(jù)到達接收端主機的輸入緩沖區(qū),注意這個接收過程也不受應(yīng)用程序控制,而是由接收端內(nèi)核協(xié)議棧完成,其中包括發(fā)送ack確認等。

  4. 數(shù)據(jù)由套接字接收緩沖區(qū)復制到接收端應(yīng)用程序緩沖區(qū),注意這個過程是由類似read等函數(shù)來完成。

2、阻塞方式的情況

?阻塞方式下,如果服務(wù)端一直sleep不接收數(shù)據(jù),而客戶端一直write,也就是只能執(zhí)行上述過程中的前三步,這樣最終結(jié)果肯定是接收端的輸入緩沖區(qū)和發(fā)送端的輸出緩沖區(qū)都被填滿,這樣write就無法繼續(xù)將數(shù)據(jù)從應(yīng)用程序復制到發(fā)送端的輸出緩沖區(qū)了,從而使進程進入睡眠。

3、非阻塞方式的情況

?非阻塞情況下,服務(wù)端一直sleep,客戶端一直write數(shù)據(jù)的結(jié)果:開始客戶端write成功,隨著客戶端write,接收端的輸入緩沖區(qū)和發(fā)送端的輸出緩沖區(qū)會被填滿。當發(fā)送端的輸出緩沖區(qū)的可用空間小于write請求寫的字節(jié)數(shù)時,write立即返回-1,并將errno置為EWOULDBLOCK。

UDP的接收緩沖區(qū): 每個UDP Socket都有一個接收緩沖區(qū),沒有發(fā)送緩沖區(qū)。有數(shù)據(jù)就直接發(fā)送,不管對方是否能夠正確接收,也不管對端接收緩沖區(qū)是否已經(jīng)滿了。 UDP是沒有流量控制的;快的發(fā)送者可以很容易地就淹沒慢的接收者,導致接收方的UDP丟棄數(shù)據(jù)報




socket套接字及緩沖區(qū)詳解(一篇搞定~)的評論 (共 條)

分享到微博請遵守國家法律
博爱县| 和田市| 察隅县| 九龙城区| 南平市| 上蔡县| 历史| 富裕县| 桦川县| 婺源县| 溧阳市| 牡丹江市| 晋城| 建湖县| 长子县| 淮安市| 河北区| 集安市| 清原| 奎屯市| 鄂托克旗| 固镇县| 卢龙县| 图木舒克市| 册亨县| 库尔勒市| 大港区| 峨山| 克拉玛依市| 博兴县| 博罗县| 宜都市| 含山县| 申扎县| 德庆县| 平阴县| 镇原县| 尼木县| 丹棱县| 尤溪县| 荣昌县|