国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select

這篇具有很好參考價(jià)值的文章主要介紹了【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select。希望對(duì)大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請(qǐng)大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問(wèn)。

??作者:一只大喵咪1201
??專欄:《網(wǎng)絡(luò)》
??格言:你只管努力,剩下的交給時(shí)間!
【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++

??五種IO模型

在學(xué)習(xí)系統(tǒng)部分的時(shí)候,本喵就講解過(guò)IO,當(dāng)時(shí)我們學(xué)習(xí)的IO就是從文件中讀數(shù)據(jù)和寫(xiě)數(shù)據(jù),到了后來(lái)學(xué)習(xí)網(wǎng)絡(luò)的時(shí)候,我們知道,從網(wǎng)絡(luò)中讀取和寫(xiě)入數(shù)據(jù)也是IO,那么IO到底是什么呢?今天我們來(lái)更深刻的認(rèn)識(shí)一下IO。

就拿讀取數(shù)據(jù)來(lái)說(shuō),無(wú)論是調(diào)用read還是recv,在文件描述符所指向的struct file中的接收緩沖區(qū)如果沒(méi)有數(shù)據(jù)的時(shí)候,都會(huì)阻塞等待。

當(dāng)緩沖區(qū)中有數(shù)據(jù)后,才會(huì)進(jìn)行讀取,所謂讀取,本質(zhì)就是在拷貝,就是將內(nèi)核緩沖區(qū)中的數(shù)據(jù)拷貝到用戶緩沖區(qū)中供用戶去使用。

無(wú)論是等待還是拷貝,都是讀取的過(guò)程,二者缺一不可。

  • IO = 等 + 數(shù)據(jù)拷貝

那么什么是高效的IO呢?我們知道,IO過(guò)程中我們?cè)谝獾氖强截?,而不是等待,由于各種技術(shù)的發(fā)展,拷貝所花費(fèi)的時(shí)間幾乎是固定的,是由電路或者系統(tǒng)等等機(jī)制來(lái)保證的,所以拷貝的效率已經(jīng)很難再有提升了。

  • 高效的IO = 減少等待的比重

IO的種類有五種,下面本喵給大家介紹一下:

  1. 阻塞IO:在內(nèi)核將數(shù)據(jù)準(zhǔn)備好之前,系統(tǒng)調(diào)用會(huì)一直等待,所有的套接字以及文件,默認(rèn)都是阻塞方式。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示便是阻塞IO的示意圖,在進(jìn)程調(diào)用recvfrom從內(nèi)核緩沖區(qū)中讀取數(shù)據(jù)時(shí),如果數(shù)據(jù)沒(méi)有準(zhǔn)備好,進(jìn)程就會(huì)阻塞在調(diào)用處等待,直到數(shù)據(jù)準(zhǔn)備好,才會(huì)將內(nèi)核緩沖區(qū)的數(shù)據(jù)拷貝到用戶緩沖區(qū),并且給進(jìn)程返回值。

  • 阻塞IO是最常見(jiàn)的IO模型,也是最簡(jiǎn)單的IO模型,我們之前寫(xiě)的所有IO都是阻塞式的。
  1. 非阻塞IO:如果內(nèi)核還未將數(shù)據(jù)準(zhǔn)備好,系統(tǒng)調(diào)用仍然會(huì)直接返回,并且返回EAGAN或者EWOULDBLOCK錯(cuò)誤碼。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++

如上圖所示,進(jìn)程調(diào)用recvfrom從內(nèi)核緩沖區(qū)中讀取數(shù)據(jù)時(shí),即使數(shù)據(jù)沒(méi)有準(zhǔn)備好,仍然會(huì)給進(jìn)程一個(gè)返回一個(gè)EAGAN或者EWOULDBLOCK

通常情況下使用這種IO方式時(shí),如果返回EAGAN或者EWOULDBLOCK,說(shuō)明數(shù)據(jù)沒(méi)有準(zhǔn)備好,就會(huì)再次調(diào)用recvfrom去讀取數(shù)據(jù),如此反復(fù),直到數(shù)據(jù)準(zhǔn)備好并且完成拷貝,最后返回表示成的返回值。

  • 非阻塞IO需要程序員以循環(huán)的方式反復(fù)嘗試讀寫(xiě)文件描述符,這個(gè)過(guò)程稱為輪詢
  • 這對(duì)CPU來(lái)說(shuō)是較大的浪費(fèi),一般只有特定場(chǎng)景下才使用。

默認(rèn)情況下,文件描述符fd指向的struct file中的緩沖區(qū)的阻塞式IO,所以我們前面無(wú)論是在進(jìn)行文件操縱還是使用套接字的時(shí)候,都是阻塞IO。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示系統(tǒng)調(diào)用fcntl,可以使用它將fd所指向的文件改成非阻塞IO模式,它的參數(shù)是一個(gè)可變參數(shù)。

  • int fd:要修改文件的文件描述符fd。
  • 返回值fl:大于0表示當(dāng)前文件的狀態(tài),小于0表示調(diào)用失敗。
  • int cmd:對(duì)fd所指向的文件要進(jìn)行的操作,可以傳遞兩個(gè)參數(shù):
  • F_GETFL:用來(lái)獲取該文件當(dāng)前的狀態(tài)。
  • F_SETFL:用來(lái)設(shè)置該文件當(dāng)前的狀態(tài)。
  • 可變參數(shù)部分:可以傳遞參數(shù)有O_RDONLY,O_WRONLY等等,最重要的是O_NONBLOCK非阻塞IO方式,但是在傳參的時(shí)候,必須和fl進(jìn)行按位或,如fl | O_NONBLOCK。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示代碼是本喵寫(xiě)的一個(gè)工具函數(shù),作用就是將指定fd所代表的文件設(shè)置成非阻塞IO方式。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖,從內(nèi)核中的代碼可以看到,O_NONBLOCK是一個(gè)宏,僅僅代表著一個(gè)比特位的狀態(tài),所以在傳參時(shí),需要使用fl | O_NONBLOCK的方式,在文件原有的狀態(tài)上增加非阻塞。

再重新來(lái)看一下read系統(tǒng)調(diào)用:

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示為man手冊(cè)中的描述,調(diào)用失敗以后,返回-1,并且錯(cuò)誤碼被設(shè)置。

  • 設(shè)置不同的錯(cuò)誤碼代表著不同的意義。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,可以設(shè)置的錯(cuò)誤碼有這么多,雖然返回值是-1,但是不同的錯(cuò)誤碼代表著不同的情況,其中EAGAIN或者EWOULDBLOCK表示的就是數(shù)據(jù)沒(méi)有準(zhǔn)備好,需要稍后再讀。

  • 讀取數(shù)據(jù)時(shí),內(nèi)核中緩沖區(qū)的數(shù)據(jù)沒(méi)有準(zhǔn)備好并沒(méi)有錯(cuò),這是很正常的情況。
  • 所以錯(cuò)誤碼EAGAIN并不表示錯(cuò)誤了,只是表示數(shù)據(jù)暫時(shí)沒(méi)有準(zhǔn)備好,需要稍后再來(lái)讀取。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,EAGAINEWOULDBLOCK都是宏,而且它們的值都是11,本質(zhì)上是一個(gè)東西。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖代碼所示,使用本喵寫(xiě)的工具serNonBlock將標(biāo)準(zhǔn)輸入,也就是文件描述符為0的文件設(shè)置成非阻塞IO模式,然后運(yùn)行。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,可以看到,輸入提示符>>>在不停打印,在本喵從鍵盤(pán)上輸入的時(shí)候,仍然在打印,雖然輸入的內(nèi)容被>>>分隔開(kāi)了,但是輸入完成以后,回顯echo的內(nèi)容卻是完整的,仍然是helloworld。

  • 輸入和輸出互不影響,因?yàn)橛休斎刖彌_區(qū)和輸出緩沖區(qū),二者是相互獨(dú)立的。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示便是默認(rèn)情況下的阻塞IO,可以看到,輸入和輸出輪替進(jìn)行著,在本喵沒(méi)有輸入的情況下,該進(jìn)程是阻塞等待的。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,可以在else情況,也就是返回值s小于0的時(shí)候再進(jìn)行具體的判斷,如果錯(cuò)誤碼errno的值是EAGAIN說(shuō)明只是數(shù)據(jù)沒(méi)有準(zhǔn)備好,并不是出錯(cuò)了,在等待數(shù)據(jù)就緒的過(guò)程中可以執(zhí)行其他任務(wù)。
【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,此時(shí)進(jìn)程并沒(méi)有阻塞,而是在輪詢,數(shù)據(jù)沒(méi)有準(zhǔn)備好就執(zhí)行其他任務(wù)來(lái)打發(fā)時(shí)間。

  1. 信號(hào)驅(qū)動(dòng)IO:內(nèi)核將數(shù)據(jù)準(zhǔn)備好的時(shí)候,使用SIGIO信號(hào)通知應(yīng)用程序進(jìn)行IO操作。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++

如上圖所示信號(hào)驅(qū)動(dòng)IO模型,該模式調(diào)用recvfrom并不是在主進(jìn)程中調(diào)用,而且使用signal注冊(cè)信號(hào)處理函數(shù),在信號(hào)處理函數(shù)中調(diào)用recvfrom

進(jìn)程一直在正常運(yùn)行,執(zhí)行自己的邏輯,當(dāng)內(nèi)核接收緩沖區(qū)有數(shù)據(jù)到來(lái)時(shí),進(jìn)程會(huì)收到系統(tǒng)給發(fā)的信號(hào)SIGIO,然后就會(huì)調(diào)用該信號(hào)注冊(cè)的處理方式,在信號(hào)處理方式中調(diào)用recvfrom讀取緩沖區(qū)中的數(shù)據(jù)。

  • 一旦進(jìn)入信號(hào)處理函數(shù)中,說(shuō)明內(nèi)核緩沖區(qū)中的數(shù)據(jù)已經(jīng)準(zhǔn)備好了,在這里只需要讀取,而不再需要等待。
  1. IO多路轉(zhuǎn)接:雖然從流程圖上看起來(lái)和阻塞IO類似,實(shí)際上最核心在于IO多路轉(zhuǎn)接能夠同時(shí)等待多個(gè)文件描述符的就緒狀態(tài)。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖IO多路轉(zhuǎn)接模式,該模式中,將IO的等待拷貝兩個(gè)步驟分開(kāi)了。

進(jìn)程調(diào)用select系統(tǒng)調(diào)用來(lái)等待內(nèi)核緩沖區(qū)中數(shù)據(jù)就緒,當(dāng)數(shù)據(jù)就緒以后通知進(jìn)程調(diào)用recvfrom來(lái)將數(shù)據(jù)拷貝到用戶緩沖區(qū)中。

這樣看起來(lái)和信號(hào)驅(qū)動(dòng)的IO模式?jīng)]有什么區(qū)別,但是多路轉(zhuǎn)接的優(yōu)勢(shì)在于可以同時(shí)等待多個(gè)文件描述符所指向的文件。

  • IO多路轉(zhuǎn)接模式下,可以同時(shí)等待多個(gè)文件,當(dāng)一個(gè)或者多個(gè)文件的緩沖區(qū)中數(shù)據(jù)就緒時(shí),就會(huì)通知上層用戶來(lái)讀取。

此時(shí)雖然也有等,但是等的比重就降低了,因?yàn)槟軌蛞淮蔚却鄠€(gè)文件,進(jìn)而讓上層用戶一次來(lái)讀取多個(gè)緩沖區(qū)中的數(shù)據(jù),拷貝的比重就增加了,從而提高了IO的效率。

  1. 異步IO:由內(nèi)核在數(shù)據(jù)拷貝完成時(shí),通知應(yīng)用程序直接去用戶緩沖區(qū)中使用數(shù)據(jù)。
  • 同步和異步關(guān)注的是消息通信機(jī)制:
  • 所謂同步,就是在發(fā)出一個(gè)調(diào)用時(shí),在沒(méi)有得到結(jié)果之前,該調(diào)用就不返回,但是一旦調(diào)用返回,就得到返回值了。
  • 也就是由調(diào)用者主動(dòng)等待這個(gè)調(diào)用的結(jié)果。

異步則是相反,調(diào)用在發(fā)出之后,這個(gè)調(diào)用就直接返回了,所以沒(méi)有返回結(jié)果。

  • 當(dāng)一個(gè)異步過(guò)程調(diào)用發(fā)出后,調(diào)用者不會(huì)立刻得到結(jié)果,而是在調(diào)用發(fā)出后,被調(diào)用者通過(guò)狀態(tài)、信號(hào)等來(lái)通知調(diào)用者,或通過(guò)回調(diào)函數(shù)處理這個(gè)調(diào)用。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示異步IO模式示意圖,進(jìn)程調(diào)用aio_read,將等待數(shù)據(jù)就緒和將數(shù)據(jù)拷貝到用戶緩沖區(qū)兩個(gè)步驟的工作全部交給操作系統(tǒng)來(lái)完成。

當(dāng)操作系統(tǒng)完成兩個(gè)步驟以后,通知上層用戶直接去用戶緩沖區(qū)中使用數(shù)據(jù)即可。

信號(hào)驅(qū)動(dòng)是告訴進(jìn)程可以從內(nèi)核緩沖區(qū)中拷貝數(shù)據(jù)到用戶緩沖區(qū)了,而異步IO連拷貝這一步也不用做了,直接使用數(shù)據(jù)。

  • 另外,我們回憶在學(xué)習(xí)多進(jìn)程多線程的時(shí)候,也提到同步和互斥,這里的同步通信和進(jìn)程之間的同步是完全不同的概念。
  • 進(jìn)程/線程同步也是進(jìn)程/線程之間直接的制約關(guān)系,是為完成某種任務(wù)而建立的兩個(gè)或多個(gè)線程,這個(gè)線程需要在某些位置上協(xié)調(diào)他們的工作次序而等待、傳遞信息所產(chǎn)生的制約關(guān)系。尤其是在訪問(wèn)臨界資源的時(shí)候。

比較這五種IO模式,阻塞IO模式肯定是效率最低的,非阻塞以及信號(hào)驅(qū)動(dòng)的IO模式,同樣需要參加IO的等待拷貝兩個(gè)過(guò)程,對(duì)于IO的效率是相同的。

異步IO模式也是同樣的道理,雖然等待和拷貝不是由線程去做的,而是由操作系統(tǒng)在做,但是線程也得在等待和拷貝完成后才能使用數(shù)據(jù),所以IO的效率還是沒(méi)有提高的。

而多路轉(zhuǎn)接不一樣,雖然等待拷貝兩個(gè)過(guò)程都參與,但是等待時(shí)可以一次等待多個(gè)文件描述符,拷貝時(shí)也是可以拷貝多個(gè)文件描述符中的數(shù)據(jù)。

  • 由于等待的文件描述符數(shù)量多,所以有數(shù)據(jù)就緒的概率就高,進(jìn)行拷貝也更加頻繁。
  • 站在上帝視角來(lái)看,多路轉(zhuǎn)接模式下,進(jìn)程在單位時(shí)間內(nèi)進(jìn)行拷貝的次數(shù)要比其他幾種模式多。

所以多路轉(zhuǎn)接更加高效,而我們研究的重點(diǎn)也在多路轉(zhuǎn)接模式上,主要有selectpoll,epoll三種方式。

??select

??認(rèn)識(shí)接口

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,該系統(tǒng)調(diào)用有5個(gè)參數(shù)。

  • int nfds:要等待的所有文件描述符中的最大fd+1。

假設(shè)現(xiàn)在要等待的文件有3個(gè),文件描述符分別是3,4,7,則傳參時(shí)就需要傳7+1=8給nfds。

  • fd_set* reads:等待讀取就緒文件描述符的位圖。

select等待的文件有不同的事件會(huì)就緒,比如讀取就緒,寫(xiě)就緒,錯(cuò)誤就緒等等。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示是fd_set類型在內(nèi)核中的定義,可以看到它就是一個(gè)位圖。它有多個(gè)比特位,每一個(gè)比特位代表一個(gè)文件描述符,比特位的狀態(tài)表示該比特位是否被監(jiān)聽(tīng)。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示便是fd_set位圖示意圖,其中比特位的順序由低到高從左向右,比特位的下標(biāo)就是代表文件描述符fd,比特位的內(nèi)容表示狀態(tài),這張圖中,文件描述符為1,3,1023的三個(gè)文件描述符需要被select監(jiān)視。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,使用sizeof得到fd_set類型的大小是8字節(jié),所以有1024個(gè)比特位,這意味著使用select最多監(jiān)視1024個(gè)文件描述符。

將接收緩沖區(qū)所在文件的文件描述符設(shè)置到readfds中,當(dāng)該緩沖區(qū)有數(shù)據(jù)到來(lái)時(shí)(讀就緒),select就會(huì)通知上層進(jìn)程去讀取該緩沖區(qū)中的數(shù)據(jù)。

  • fd_set* writefds:等待寫(xiě)入就緒文件描述符所在位圖。

該位圖和readfds一樣,只是操作系統(tǒng)等待的事件由讀就緒變成了寫(xiě)就緒,當(dāng)發(fā)送緩沖區(qū)空了以后(寫(xiě)就緒),操作系統(tǒng)就會(huì)通知上層進(jìn)程向該緩沖區(qū)中寫(xiě)入數(shù)據(jù)。

  • fd_set* exceptfds:等待異常就緒文件描述符所在位圖。

打開(kāi)的文件,如TCP中的套接字,當(dāng)對(duì)端關(guān)閉套接字以后,自己這邊的套接字就會(huì)出現(xiàn)異常,此時(shí)操作系統(tǒng)就會(huì)通知上層進(jìn)程處理該異常。

需要操作系統(tǒng)監(jiān)視哪里事件就將對(duì)應(yīng)的位圖傳給select,待事件就緒后就會(huì)通知上層進(jìn)程去處理,如果不需要監(jiān)視直接設(shè)置成nullptr就行。

  • struct timeval* timeout:設(shè)置等待方式。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++

如上圖所示struct timeval類型的定義,有兩個(gè)成員,第一個(gè)是秒,第二個(gè)是微秒。

該參數(shù)傳入nullptr的時(shí)候,select是阻塞等待,只有當(dāng)一個(gè)或者多個(gè)文件描述符就緒時(shí)才會(huì)通知上層進(jìn)程去讀取數(shù)據(jù)。

該參數(shù)如果是struct timeval timeout = {0, 0},時(shí)間設(shè)置成0,select是非阻塞等待,就需要使用輪詢的方式。

該參數(shù)如果設(shè)置了具體值,如struct timeval timeout = {5, 0},時(shí)間設(shè)置成5,select在5秒內(nèi)阻塞等待,如果在5秒內(nèi)有文件描述符就緒,則通知上層,如果沒(méi)有文件描述符就緒則超時(shí)返回。

  • 返回值:

ret > 0表示有ret個(gè)fd就緒了,ret == 0表示超時(shí)返回,ret < 0表示select調(diào)用失敗了。


為了使用方便,內(nèi)核還提供了一組宏供用戶去設(shè)置fd_set位圖,將對(duì)應(yīng)的文件描述符設(shè)置進(jìn)去,避免了我們自己使用按位或等運(yùn)算給位圖賦值的麻煩:

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,FD_CLR是將位圖中指定文件描述符fd所對(duì)應(yīng)位的狀態(tài)清零,表示不用操作系統(tǒng)再等待該文件。

FD_ISSET是用來(lái)判斷特定文件描述符fd是否被設(shè)置進(jìn)了位圖,如果設(shè)置返回1,沒(méi)有則返回0。

FD_SET是用來(lái)將指定文件描述符fd對(duì)應(yīng)的位圖設(shè)置為1,表示需要操作系統(tǒng)等待該文件。

FD_ZERO是用來(lái)將整個(gè)位圖清空的,此時(shí)操作系統(tǒng)不等待任何一個(gè)文件。


select的五個(gè)參數(shù)中,后面四個(gè)都是輸入輸出型參數(shù),都是傳的指針,意味著操作系統(tǒng)和用戶共用一個(gè)參數(shù)。

調(diào)用select傳參時(shí),表示用戶告訴內(nèi)核,需要操作系統(tǒng)等待哪個(gè)文件,以及哪種事件。操作系統(tǒng)第一時(shí)間會(huì)將傳入的位圖參數(shù)清空,每就緒一個(gè)文件,傳入位圖相應(yīng)比特位置一,然后傳返回值給用戶。

此時(shí)就是內(nèi)核在告訴用戶,你關(guān)心的多個(gè)fd,有哪些已經(jīng)就緒了。

用戶根據(jù)返回值來(lái)處理調(diào)用結(jié)果,如果是ret>0,則判斷自己當(dāng)初設(shè)置進(jìn)位圖中的文件描述符是否被置一了,如果置一了,說(shuō)明該文件所對(duì)應(yīng)的事件就緒了,用戶就可以進(jìn)行進(jìn)一步處理。

  • 由于傳入的參數(shù)是輸入輸出型的,操作系統(tǒng)等待后的結(jié)果也是在這個(gè)參數(shù)中,所以用戶必須自己再維護(hù)一個(gè)數(shù)據(jù)結(jié)構(gòu)來(lái)記錄自己最初設(shè)置要等待的文件描述符。
  • 根據(jù)select返回狀態(tài)以及操作系統(tǒng)修改后的位圖,與自己維護(hù)的記錄結(jié)構(gòu)作對(duì)比,得出自己當(dāng)初要等待的文件是否就緒的結(jié)論。

無(wú)論是讀取數(shù)據(jù),還是寫(xiě)入數(shù)據(jù),再或者是異常事件,都是采用這樣的方式和機(jī)制。

struct timeval* timeout表示的阻塞等待時(shí)間,操作系統(tǒng)內(nèi)部也會(huì)進(jìn)行修改,假設(shè)初值是{5, 0}表示阻塞等待5s中,如果5s內(nèi)沒(méi)有事件就緒則select返回0,表示超時(shí)返回,此時(shí)原本傳入的time的值也變成了{0, 0}

如果5s內(nèi)有事件就緒,假設(shè)操作系統(tǒng)等待了3秒,selsect返回值大于0,表示不是超時(shí)返回,有事件就緒,此時(shí)原本傳入的time的值也變成了{2, 0},表示設(shè)置的阻塞事件還剩兩秒。

  • 所以在輪詢過(guò)程中,每循環(huán)一次就需要重新設(shè)置一下時(shí)間,否則第一次超時(shí)返回后,time的值就成了0,之后select就成了非阻塞IO,與初衷不符。
  • 輸入輸出型參數(shù)的作用就是讓用戶和內(nèi)核之間相互溝通,互相知曉對(duì)方要關(guān)心的。

??簡(jiǎn)易select服務(wù)器

本喵將創(chuàng)建套接字的代碼封裝成了一個(gè)Sock類,使用的時(shí)候直接調(diào)用即可,同樣可以將其作為一個(gè)小組件。
【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖上,Sock類中包含套接字的創(chuàng)建,綁定,監(jiān)聽(tīng),以及獲取新連接等四個(gè)方法,這些函數(shù)中還包含日志信息,具體的日志代碼本喵就不貼了,有興趣的小伙伴自行去查閱日志功能。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示便是select簡(jiǎn)易服務(wù)器的基本配置,成員變量包含監(jiān)聽(tīng)套接字,端口號(hào),用戶維護(hù)的用于設(shè)置等待位圖的數(shù)組_fdarry,以及回調(diào)函數(shù)。

定義了幾個(gè)全局默認(rèn)變量,包括默認(rèn)端口號(hào),select所能等待文件的上限1024,以及用戶維護(hù)數(shù)組的初始默認(rèn)值。

  • initServer():初始化服務(wù)器

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,第一步便是初始化服務(wù)器,在系統(tǒng)中創(chuàng)建套接字,進(jìn)行綁定和監(jiān)聽(tīng),構(gòu)建完整的會(huì)話層。之后將用戶維護(hù)的用來(lái)設(shè)置等待位圖的數(shù)組進(jìn)行初始化,大小是1024個(gè)元素,初始值都是-1。

  • 0,1,2文件描述符不用select等待,從listen套接字開(kāi)始進(jìn)行等待。
  • Start():?jiǎn)?dòng)服務(wù)器

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,服務(wù)器在啟動(dòng)后,是一個(gè)while(1)的死循環(huán),在這個(gè)循環(huán)中進(jìn)行一遍又一遍的輪詢。

由于select的后面四個(gè)參數(shù)都是輸入輸出型參數(shù),所以每一次輪詢之前都需要重新設(shè)置一遍,否則就會(huì)因?yàn)椴僮飨到y(tǒng)的修改而出現(xiàn)問(wèn)題。需要重新設(shè)置位圖狀態(tài),重新設(shè)置等待時(shí)間等等。

  • 每次輪詢的時(shí)候,都需要將用戶維護(hù)的數(shù)組中需要等待的文件描述符重新設(shè)置到fd_set位圖中。

在將參數(shù)設(shè)置好以后便調(diào)用select系統(tǒng)調(diào)用,用switch將返回的情況分別處理,當(dāng)n>0時(shí),說(shuō)明有文件就緒,可以去讀取,所以調(diào)用HandlerReadEvent函數(shù)去處理該事件。

事件處理函數(shù):
【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,當(dāng)執(zhí)行到該函數(shù)的時(shí)候,必有套接字就緒,此時(shí)用戶要做的就是判斷到底是哪個(gè)套接字上事件就緒。

第一次執(zhí)行該函數(shù)的時(shí)候,必然是監(jiān)聽(tīng)套接字就緒,因?yàn)楫?dāng)前select等待的只有這一個(gè)套接字,所以判斷符合條件以后,去執(zhí)行Accepter函數(shù)來(lái)獲取新連接。

  • 監(jiān)聽(tīng)套接字就緒也是屬于讀事件就緒,因?yàn)榇藭r(shí)有新連接到來(lái),需要用戶去將新連接讀取走。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,當(dāng)監(jiān)聽(tīng)套接字就緒后,用戶第一時(shí)間肯定就是讀取監(jiān)聽(tīng)到的新連接,并且獲取客戶端的IP地址以及端口號(hào)。

新連接獲取成功后,由于此時(shí)沒(méi)有客戶端的數(shù)據(jù)到來(lái),所以新連接套接字沒(méi)有就緒。

  • 此時(shí)必須將新連接套接字交給select去等待就緒,所以需要向用戶層維護(hù)的數(shù)組中添加該套接字的文件描述符。
  • 如果此時(shí)直接讀取新連接套接字的話,由于沒(méi)有就緒,就會(huì)阻塞在這里,服務(wù)器無(wú)法繼續(xù)執(zhí)行下去,與我們的初衷就不符合了。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
為了方便,本喵還增加了一個(gè)Print函數(shù),打印新增加的需要select等待的文件描述符。


第一次之后調(diào)用Accepter函數(shù)時(shí),已經(jīng)就緒的文件就不一定是監(jiān)聽(tīng)套接字了,有可能是前面獲取的新連接套接字,所以就需要進(jìn)行具體判斷到底是哪個(gè)套接字就緒了。當(dāng)新連接套接字就緒后,就調(diào)用Recver從套接字中讀取客戶端的請(qǐng)求。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,當(dāng)新連接套接字就緒以后,首先要進(jìn)行的就是讀取套接字中客戶端發(fā)來(lái)的數(shù)據(jù),使用recv獲取數(shù)據(jù)。

  • 當(dāng)前這種讀取數(shù)據(jù)的方式是存在一定問(wèn)題的,因?yàn)椴荒鼙WC套接字中的數(shù)據(jù)是否被讀完了。

但是此時(shí)并不會(huì)產(chǎn)生影響,所以暫且這樣,后面本喵會(huì)制定具體的協(xié)議去處理它。

如果讀取數(shù)據(jù)出現(xiàn)了問(wèn)題,或者套接字出現(xiàn)異常,那么就需要關(guān)閉套接字,并且將文件描述符從用戶維護(hù)的數(shù)組中清除。

讀取成功后將請(qǐng)求處理,并且構(gòu)建響應(yīng)發(fā)送給客戶端,當(dāng)前的select服務(wù)端的重點(diǎn)在于讀取,所以寫(xiě)入本喵這里就不詳細(xì)寫(xiě)了。


  • selectServer.cpp

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示就是selectServer.cpp中的代碼,服務(wù)器的回調(diào)函數(shù)中僅是將客戶端發(fā)送來(lái)的數(shù)據(jù)原封不動(dòng)的響應(yīng)給客戶端,沒(méi)有做其他處理,其他部分代碼本喵不再解釋。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,當(dāng)服務(wù)器開(kāi)始運(yùn)行后,由于此時(shí)沒(méi)有新連接到來(lái),所以監(jiān)聽(tīng)套接字一直處于未就緒的狀態(tài),前面在設(shè)置等待事件的時(shí)候設(shè)置了5s,所以每隔5s就超時(shí)返回一次。

  • 可以看到當(dāng)前最大文件描述符是3,也就是監(jiān)聽(tīng)套接字的文件描述符。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
如上圖所示,為了避免超時(shí)返回的干擾,本喵將select的最后一個(gè)參數(shù)也設(shè)置成nullptr此時(shí)select就是阻塞等待,根據(jù)運(yùn)行結(jié)果也可以看成是阻塞不動(dòng)的。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++

如上圖所示,此時(shí)使用兩個(gè)telnet連接客戶端,可以看到服務(wù)端提示有新事件就緒,此時(shí)是監(jiān)聽(tīng)套接字監(jiān)聽(tīng)到了兩個(gè)客戶端連接,所以顯示兩次,服務(wù)端每處理一次,用戶層維護(hù)的數(shù)組中文件名描述符就會(huì)增加一個(gè),所以最終是3,4,5三個(gè)文件需要select進(jìn)行等待。

兩個(gè)客戶端向服務(wù)端發(fā)送消息的時(shí)候,服務(wù)端顯示事件就緒,這是進(jìn)行數(shù)據(jù)通信的套接字上有數(shù)據(jù)到來(lái),提醒用戶層去讀取數(shù)據(jù)。

  • 服務(wù)器上只有一個(gè)進(jìn)程(線程),客戶端有多個(gè),此時(shí)服務(wù)端可以同時(shí)接收多個(gè)客戶端的連接請(qǐng)求和數(shù)據(jù)。
  • 多路轉(zhuǎn)接實(shí)現(xiàn)了我們之前只能通過(guò)多進(jìn)程或者多線程才能實(shí)現(xiàn)的功能,而且效率非常高。

??select的特點(diǎn)

  1. select能同時(shí)等待的文件fd是有上限的,除非重新修改內(nèi)核,否則無(wú)法解決。

fd_set位圖大小只有1024個(gè)比特位,意味著select同時(shí)最多只能等待1024個(gè)文件描述符。

【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select,網(wǎng)絡(luò),網(wǎng)絡(luò),開(kāi)發(fā)語(yǔ)言,c++
可以看到,本喵的Linux機(jī)器上,最多可以打開(kāi)100001個(gè)文件,遠(yuǎn)大于1024,所以說(shuō)select能夠同時(shí)等待的文件數(shù)量在高訪問(wèn)量的服務(wù)器中是遠(yuǎn)遠(yuǎn)不夠的。

  1. 必須借助第三方數(shù)組等結(jié)構(gòu)來(lái)維護(hù)需要select等待的文件描述符fd。

由于select的后四個(gè)參數(shù)都是輸入輸出型參數(shù),操作系統(tǒng)也會(huì)修改這幾個(gè)參數(shù),這就導(dǎo)致用戶層必須自己維護(hù)一個(gè)數(shù)組來(lái)記錄自己曾經(jīng)想要讓select等待的文件描述符。

并且每輪詢一次就需要重新設(shè)置一次fd_set位圖,不僅繁瑣,而且對(duì)于效率相對(duì)較低。

  1. select存在遍歷成本。

在上面本喵實(shí)現(xiàn)的服務(wù)器代碼中,對(duì)于用戶層來(lái)說(shuō),存在多處遍歷所維護(hù)的數(shù)組。

在將文件描述符設(shè)置到fd_set位圖中的時(shí)候,需要遍歷數(shù)組中的所有元素來(lái)找到合法的fd設(shè)置到位圖中。

select完成等待后,同樣需要遍歷一次數(shù)組,來(lái)確定是哪個(gè)fd的事件就緒了,然后再去處理。

  1. 內(nèi)核也要進(jìn)行遍歷

select的第一個(gè)參數(shù)傳參時(shí)傳入的是最大文件描述符fd + 1,這個(gè)參數(shù)就是為了讓內(nèi)核確定遍歷的范圍,這個(gè)值之前的所有文件描述符,操作系統(tǒng)都會(huì)進(jìn)行查看,看看是否有事件就緒。

  1. 內(nèi)核和用戶層來(lái)回拷貝的成本問(wèn)題

select采用的是位圖來(lái)標(biāo)記哪個(gè)文件的事件就緒,無(wú)論是用戶層告訴內(nèi)核,還是內(nèi)核告訴用戶層,都需要拷貝,這樣來(lái)回進(jìn)行數(shù)據(jù)拷貝也是有很大的成本。


??總結(jié)

多路轉(zhuǎn)接是一個(gè)非常重要的IO模式,而select方式只最基礎(chǔ)的一種,它主要的作用是帶領(lǐng)我們理解多路轉(zhuǎn)接,后面本喵還會(huì)講解pollepoll方式。文章來(lái)源地址http://www.zghlxwxcb.cn/news/detail-685255.html

到了這里,關(guān)于【網(wǎng)絡(luò)】多路轉(zhuǎn)接——五種IO模型 | select的文章就介紹完了。如果您還想了解更多內(nèi)容,請(qǐng)?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來(lái)自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場(chǎng)。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請(qǐng)注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請(qǐng)點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • I/O多路轉(zhuǎn)接之select

    2023年04月10日
    瀏覽(16)
  • 網(wǎng)絡(luò)編程 IO多路復(fù)用 [select版] (TCP網(wǎng)絡(luò)聊天室)

    網(wǎng)絡(luò)編程 IO多路復(fù)用 [select版] (TCP網(wǎng)絡(luò)聊天室)

    //head.h? ? ? ? ? ? ? ? ?頭文件 //TcpGrpSer.c? ? ? ? 服務(wù)器端 //TcpGrpUsr.c? ? ? ? 客戶端 select函數(shù)? 功能:阻塞函數(shù),讓內(nèi)核去監(jiān)測(cè)集合中的文件描述符是否準(zhǔn)備就緒,若準(zhǔn)備就緒則解除阻塞。 原型: head.h TcpGrpSer.c TcpGrpUsr.c ? ?

    2024年02月14日
    瀏覽(25)
  • IO多路復(fù)用中select的TCP服務(wù)器模型和poll服務(wù)模型

    服務(wù)器端 客戶端 poll客戶端

    2024年02月12日
    瀏覽(32)
  • 多路轉(zhuǎn)接方案:select poll epoll 介紹和對(duì)比

    多路轉(zhuǎn)接方案:select poll epoll 介紹和對(duì)比

    內(nèi)存和外設(shè)的交互叫做IO,網(wǎng)絡(luò)IO就是將數(shù)據(jù)在內(nèi)存和網(wǎng)卡間拷貝。 IO本質(zhì)就是等待和拷貝,一般等待耗時(shí)往往遠(yuǎn)高于拷貝耗時(shí)。所以提高IO效率就是盡可能減少等待時(shí)間的比重。 IO模型 簡(jiǎn)單對(duì)比解釋 阻塞IO 阻塞等待數(shù)據(jù)到來(lái) 非阻塞IO 輪詢等待數(shù)據(jù)到來(lái) 信號(hào)驅(qū)動(dòng) 信號(hào)遞達(dá)時(shí)

    2024年02月08日
    瀏覽(17)
  • 【Linux】IO多路轉(zhuǎn)接——poll接口

    【Linux】IO多路轉(zhuǎn)接——poll接口

    目錄 poll初識(shí) poll函數(shù) poll服務(wù)器 poll的優(yōu)點(diǎn) poll的缺點(diǎn) poll也是系統(tǒng)提供的一個(gè)多路轉(zhuǎn)接接口。 poll系統(tǒng)調(diào)用也可以讓我們的程序同時(shí)監(jiān)視多個(gè)文件描述符上的事件是否就緒,和select的定位是一樣的,適用場(chǎng)景也是一樣的。 poll函數(shù) poll函數(shù)的函數(shù)原型如下: 參數(shù)說(shuō)明: fds:一

    2024年02月12日
    瀏覽(18)
  • 【Linux】IO多路轉(zhuǎn)接技術(shù)Epoll的使用

    【Linux】IO多路轉(zhuǎn)接技術(shù)Epoll的使用

    ? 在學(xué)習(xí) epoll 之前,我們首先了解一下Linux中的多路復(fù)用技術(shù): 在Linux系統(tǒng)中, IO多路復(fù)用 是一種重要的技術(shù),它允許一個(gè)進(jìn)程同時(shí)監(jiān)視多個(gè)文件描述符,一旦某個(gè)描述符準(zhǔn)備好進(jìn)行讀?。ㄍǔJ亲x就緒或?qū)懢途w),內(nèi)核會(huì)通知該進(jìn)程進(jìn)行相應(yīng)的讀寫(xiě)操作。這樣,我們可以

    2024年04月27日
    瀏覽(15)
  • 【Linux網(wǎng)絡(luò)編程】TCP并發(fā)服務(wù)器的實(shí)現(xiàn)(IO多路復(fù)用select)

    【Linux網(wǎng)絡(luò)編程】TCP并發(fā)服務(wù)器的實(shí)現(xiàn)(IO多路復(fù)用select)

    服務(wù)器模型主要分為兩種, 循環(huán)服務(wù)器 和 并發(fā)服務(wù)器 。 循環(huán)服務(wù)器 : 在同一時(shí)間只能處理一個(gè)客戶端的請(qǐng)求。 并發(fā)服務(wù)器 : 在同一時(shí)間內(nèi)能同時(shí)處理多個(gè)客戶端的請(qǐng)求。 TCP的服務(wù)器默認(rèn)的就是一個(gè)循環(huán)服務(wù)器,原因是有兩個(gè)阻塞 accept函數(shù) 和recv函數(shù) 之間會(huì)相互影響。

    2024年02月03日
    瀏覽(101)
  • 【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端

    【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端

    目錄 一,往期文章 二,基本概念 IO多路復(fù)用 select 模型 poll 模型 epoll 模型 select,poll,epoll 三者對(duì)比 三,函數(shù)清單 1.select 方法 2.fd_set 結(jié)構(gòu)體 3.poll 方法 4.struct pollfd 結(jié)構(gòu)體 5.epoll_create 方法 6.epoll_ctl 方法 7.epoll_wait 方法 8.struct epoll_event 結(jié)構(gòu)體 四,代碼實(shí)現(xiàn) select 操作流程 s

    2024年02月12日
    瀏覽(31)
  • 【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端

    【高并發(fā)網(wǎng)絡(luò)通信架構(gòu)】3.引入IO多路復(fù)用(select,poll,epoll)實(shí)現(xiàn)高并發(fā)tcp服務(wù)端

    目錄 一,往期文章 二,基本概念 IO多路復(fù)用 select 模型 poll 模型 epoll 模型 select,poll,epoll 三者對(duì)比 三,函數(shù)清單 1.select 方法 2.fd_set 結(jié)構(gòu)體 3.poll 方法 4.struct pollfd 結(jié)構(gòu)體 5.epoll_create 方法 6.epoll_ctl 方法 7.epoll_wait 方法 8.struct epoll_event 結(jié)構(gòu)體 四,代碼實(shí)現(xiàn) select 操作流程 s

    2024年02月14日
    瀏覽(26)
  • 網(wǎng)絡(luò)模型與 IO 多路復(fù)用

    網(wǎng)絡(luò)模型與 IO 多路復(fù)用

    ??socket也稱作“套接字”,用于描述IP地址和端口,是一個(gè)通信鏈路的描述符。應(yīng)用程序通常通過(guò)“套接字”向?qū)Χ税l(fā)出請(qǐng)求或者應(yīng)答網(wǎng)絡(luò)請(qǐng)求。 ??socket是連接運(yùn)行在網(wǎng)絡(luò)上的兩個(gè)程序之間的通信端點(diǎn)。通信的兩端都有socket,它是一個(gè)通道,數(shù)據(jù)在兩個(gè)socket之間進(jìn)行傳輸

    2024年02月01日
    瀏覽(28)

覺(jué)得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請(qǐng)作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包