新聞中心
非阻塞模式是網(wǎng)絡(luò)編程中常見(jiàn)的一種模式,其目的是為了提高程序的并發(fā)處理能力。非阻塞模式將socket設(shè)置成非阻塞模式,使得程序在接收數(shù)據(jù)時(shí)不必等待,而是可以繼續(xù)執(zhí)行其他任務(wù),從而達(dá)到同時(shí)處理多個(gè)請(qǐng)求的目的。在Linux下,accept函數(shù)可以實(shí)現(xiàn)非阻塞模式,本文將詳細(xì)介紹。

10年積累的網(wǎng)站建設(shè)、做網(wǎng)站經(jīng)驗(yàn),可以快速應(yīng)對(duì)客戶對(duì)網(wǎng)站的新想法和需求。提供各種問(wèn)題對(duì)應(yīng)的解決方案。讓選擇我們的客戶得到更好、更有力的網(wǎng)絡(luò)服務(wù)。我雖然不認(rèn)識(shí)你,你也不認(rèn)識(shí)我。但先網(wǎng)站制作后付款的網(wǎng)站建設(shè)流程,更有浪卡子免費(fèi)網(wǎng)站建設(shè)讓你可以放心的選擇與我們合作。
1. accept函數(shù)的概述
accept函數(shù)是Linux下的網(wǎng)絡(luò)編程函數(shù)之一,用于接收客戶端發(fā)來(lái)的連接請(qǐng)求,生成一個(gè)新的socket,從而和客戶端進(jìn)行通信。accept函數(shù)的定義如下:
“`
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
“`
其中,sockfd表示服務(wù)端socket的文件描述符,addr和addrlen用于存儲(chǔ)客戶端地址信息。accept函數(shù)返回的是新生成的socket的文件描述符。
2. 非阻塞模式的實(shí)現(xiàn)
在Linux下,通過(guò)fcntl函數(shù)可以將socket設(shè)置成非阻塞模式。fcntl函數(shù)的定義如下:
“`
int fcntl(int sockfd, int cmd, … /* arg */ );
“`
其中,sockfd表示需要設(shè)置的socket的文件描述符,cmd表示控制命令,arg表示命令參數(shù)。針對(duì)accept函數(shù),需要使用以下命令將socket設(shè)置成非阻塞模式:
“`
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK);
“`
這條語(yǔ)句將socket的控制命令設(shè)置為F_SETFL,參數(shù)為fcntl(sockfd, F_GETFL, 0) | O_NONBLOCK。其中,fcntl(sockfd, F_GETFL, 0)表示獲取socket的控制命令,以便于在原有基礎(chǔ)上進(jìn)行修改;O_NONBLOCK表示將socket設(shè)置成非阻塞模式。
將socket設(shè)置成非阻塞模式后,accept函數(shù)不再是一個(gè)阻塞函數(shù)。如果沒(méi)有客戶端連接請(qǐng)求到達(dá),accept函數(shù)會(huì)立即返回-1,并設(shè)置errno為EWOULDBLOCK或EAGN,表示當(dāng)前沒(méi)有連接請(qǐng)求。如果有客戶端連接請(qǐng)求到達(dá),accept函數(shù)會(huì)返回一個(gè)新的socket的文件描述符,用于和客戶端進(jìn)行通信。
在非阻塞模式下,需要使用循環(huán)不斷地調(diào)用accept函數(shù),直到有新的連接請(qǐng)求到達(dá)。該循環(huán)中,可以使用select函數(shù)來(lái)監(jiān)聽(tīng)多個(gè)socket的狀態(tài),從而實(shí)現(xiàn)同時(shí)監(jiān)聽(tīng)多個(gè)連接請(qǐng)求的功能。
3. 非阻塞模式的優(yōu)缺點(diǎn)
非阻塞模式相比于阻塞模式有以下優(yōu)點(diǎn):
(1)提高了程序的并發(fā)處理能力。當(dāng)程序遇到阻塞操作時(shí),就需要等待該操作完成后才能繼續(xù)執(zhí)行其他任務(wù)。而在非阻塞模式下,可以不必等待某個(gè)操作完成,而是可以繼續(xù)執(zhí)行其他任務(wù),從而提高程序的并發(fā)處理能力。
(2)減少了系統(tǒng)資源的占用。在多線程編程中,如果每個(gè)線程都使用阻塞模式,則系統(tǒng)需要為每個(gè)線程分配一定的資源,從而導(dǎo)致系統(tǒng)資源的浪費(fèi)。而在非阻塞模式下,可以使用一個(gè)線程處理多個(gè)請(qǐng)求,從而減少了系統(tǒng)資源的占用。
(3)提高了響應(yīng)速度。非阻塞模式下,可以通過(guò)設(shè)置超時(shí)時(shí)間來(lái)避免程序一直等待某個(gè)操作完成而導(dǎo)致的響應(yīng)速度過(guò)慢的情況。
但是,非阻塞模式也存在一些缺點(diǎn):
(1)程序?qū)崿F(xiàn)更加復(fù)雜。非阻塞模式需要程序不斷地輪詢(xún)socket狀態(tài),從而實(shí)現(xiàn)監(jiān)聽(tīng)多個(gè)連接請(qǐng)求的功能。這會(huì)導(dǎo)致程序?qū)崿F(xiàn)更加復(fù)雜,代碼也更容易出錯(cuò)。
(2)處理數(shù)據(jù)不方便。在非阻塞模式下,需要不斷地輪詢(xún)socket狀態(tài),從而可能導(dǎo)致無(wú)法一次性讀取所有數(shù)據(jù)。這就需要程序不斷地處理數(shù)據(jù),才能保證數(shù)據(jù)能夠正確地被接收和處理。
4.
非阻塞模式是一種常見(jiàn)的網(wǎng)絡(luò)編程模式,可以提高程序的并發(fā)處理能力和響應(yīng)速度。在Linux下,可以通過(guò)將socket設(shè)置成非阻塞模式,結(jié)合select函數(shù),實(shí)現(xiàn)同時(shí)監(jiān)聽(tīng)多個(gè)連接請(qǐng)求的功能。但是,非阻塞模式也存在一些缺點(diǎn),需要在實(shí)際使用時(shí)進(jìn)行權(quán)衡和取舍。
成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!
linux網(wǎng)絡(luò)編程,為什么要將文件描述符設(shè)置成非阻塞模式
非阻塞IO 和阻塞IO:
在網(wǎng)絡(luò)編程中對(duì)于一個(gè)網(wǎng)絡(luò)句柄會(huì)遇到阻塞IO 和非阻塞IO 的概念, 這里對(duì)于這兩種socket 先做一下說(shuō)明:
基本概念:
阻塞IO::
socket 的阻塞模式意味著必須要做完IO 操作(包括錯(cuò)誤)才會(huì)
返回。
非阻塞IO::
非阻塞模式下無(wú)論操作是否完成都會(huì)立刻返回,需要通過(guò)其他方
式來(lái)判斷具體操作是否成功。(對(duì)于connect,accpet操作,通過(guò)select判斷,
對(duì)于recv,recvfrom,send,sendto通過(guò)返回值+錯(cuò)誤碼來(lái)判斷)
IO模式設(shè)置:
SOCKET
對(duì)于一個(gè)socket 是阻塞模式還是非阻塞模式的處理方法::
方法::
用fcntl 設(shè)置;用F_GETFL獲取flags,用F_SETFL設(shè)置flags|O_NONBLOCK;
同時(shí),recv,send 時(shí)使用非阻塞的方式讀取和發(fā)送消息,即flags設(shè)置為MSG_DONTWAIT
實(shí)現(xiàn)
fcntl 函數(shù)可以將一個(gè)socket 句柄設(shè)置成非阻塞模式:
flags = fcntl(sockfd, F_GETFL, 0);//獲取文件的flags值。
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK); //設(shè)置成非阻塞模式;
flags = fcntl(sockfd,F_GETFL,0);
fcntl(sockfd,F_SETFL,flags&~O_NONBLOCK); //設(shè)置成阻塞模式;
并在接收和發(fā)送數(shù)據(jù)時(shí):
將recv, send 函數(shù)的最后有一個(gè)flag 參數(shù)設(shè)置成MSG_DONTWAIT
recv(sockfd, buff, buff_size,MSG_DONTWAIT); //非阻塞模式的消息仔租發(fā)送
send(scokfd, buff, buff_size, MSG_DONTWAIT); //非阻塞模式的消息接受
普通文件
對(duì)于文件的阻塞模式還是非阻塞模式::
方法1、open時(shí),使用O_NONBLOCK;
方法2、fcntl設(shè)置,使用F_SETFL,flags|O_NONBLOCK;
消息隊(duì)列
對(duì)于消息隊(duì)列消息的發(fā)送與接受::
//非阻塞 msgsnd(sockfd,msgbuf,msgsize(不包含類(lèi)型大小),IPC_NOWAIT)
//阻塞 msgrcv(scokfd,msgbuf,msgsize(**),msgtype,IPC_NOWAIT);
讀
阻塞與非阻塞讀的區(qū)別: //
阻塞和非阻塞
的區(qū)別在于沒(méi)有數(shù)據(jù)到達(dá)的時(shí)候是否立刻返回.
讀(read/recv/msgrcv):
讀的本質(zhì)來(lái)說(shuō)其實(shí)不能是讀,在實(shí)際中, 具體的接收數(shù)據(jù)不是由這些調(diào)用來(lái)進(jìn)行,是由于系統(tǒng)底層自動(dòng)完成的。read 也好,recv 也好只負(fù)責(zé)把數(shù)據(jù)從底層緩沖copy 到我們指肢戚基定的位置.
對(duì)于讀來(lái)說(shuō)(read, 或者recv) ::
阻塞情況下::
在阻塞條件下,read/recv/msgrcv的行為::
、如果沒(méi)有發(fā)現(xiàn)數(shù)據(jù)在網(wǎng)絡(luò)緩沖中會(huì)一直等待,
、當(dāng)發(fā)現(xiàn)有數(shù)據(jù)的時(shí)候會(huì)把數(shù)據(jù)讀到用戶指定的緩沖區(qū),但是如果這個(gè)時(shí)候讀到的數(shù)歷謹(jǐn)據(jù)量比較少,比參數(shù)中指定的長(zhǎng)度要小,read 并不會(huì)一直等待下去,而是立刻返回。
read 的原則::是數(shù)據(jù)在不超過(guò)指定的長(zhǎng)度的時(shí)候有多少讀多少,沒(méi)有數(shù)據(jù)就會(huì)一直等待。
所以一般情況下::我們讀取數(shù)據(jù)都需要采用循環(huán)讀的方式讀取數(shù)據(jù),因?yàn)橐淮蝦ead 完畢不能保證讀到我們需要長(zhǎng)度的數(shù)據(jù),
read 完一次需要判斷讀到的數(shù)據(jù)長(zhǎng)度再?zèng)Q定是否還需要再次讀取。
非阻塞情況下::
在非阻塞的情況下,read 的行為::
、如果發(fā)現(xiàn)沒(méi)有數(shù)據(jù)就直接返回,
、如果發(fā)現(xiàn)有數(shù)據(jù)那么也是采用有多少讀多少的進(jìn)行處理.
所以::read 完一次需要判斷讀到的數(shù)據(jù)長(zhǎng)度再?zèng)Q定是否還需要再次讀取。
對(duì)于讀而言:: 阻塞和非阻塞的區(qū)別在于沒(méi)有數(shù)據(jù)到達(dá)的時(shí)候是否立刻返回.
recv 中有一個(gè)MSG_WAITALL 的參數(shù)::
recv(sockfd, buff, buff_size, MSG_WAITALL),
在正常情況下recv 是會(huì)等待直到讀取到buff_size 長(zhǎng)度的數(shù)據(jù),但是這里的WAITALL 也只是盡量讀全,在有中斷的情況下recv 還是可能會(huì)被打斷,造成沒(méi)有讀完指定的buff_size的長(zhǎng)度。
所以即使是采用recv + WAITALL 參數(shù)還是要考慮是否需要循環(huán)讀取的問(wèn)題,在實(shí)驗(yàn)中對(duì)于多數(shù)情況下recv (使用了MSG_WAITALL)還是可以讀完buff_size,
所以相應(yīng)的性能會(huì)比直接read 進(jìn)行循環(huán)讀要好一些。
注意:: //使用MSG_WAITALL時(shí),sockfd必須處于阻塞模式下,否則不起作用。
//所以MSG_WAITALL不能和MSG_NONBLOCK同時(shí)使用。
要注意的是使用MSG_WAITALL的時(shí)候,sockfd 必須是處于阻塞模式下,否則WAITALL不能起作用。
寫(xiě)
阻塞與非阻塞寫(xiě)的區(qū)別: //
寫(xiě)(send/write/msgsnd)::
寫(xiě)的本質(zhì)也不是進(jìn)行發(fā)送操作,而是把用戶態(tài)的數(shù)據(jù)copy 到系統(tǒng)底層去,然后再由系統(tǒng)進(jìn)行發(fā)送操作,send,write返回成功,只表示數(shù)據(jù)已經(jīng)copy 到底層緩沖,而不表示數(shù)據(jù)已經(jīng)發(fā)出,更不能表示對(duì)方端口已經(jīng)接收到數(shù)據(jù).
對(duì)于write(或者send)而言,
阻塞情況下:: //阻塞情況下,write會(huì)將數(shù)據(jù)發(fā)送完。(不過(guò)可能被中斷)
在阻塞的情況下,是會(huì)一直等待,直到write 完,全部的數(shù)據(jù)再返回.這點(diǎn)行為上與讀操作有所不同。
原因::
讀,究其原因主要是讀數(shù)據(jù)的時(shí)候我們并不知道對(duì)端到底有沒(méi)有數(shù)據(jù),數(shù)據(jù)是在什么時(shí)候結(jié)束發(fā)送的,如果一直等待就可能會(huì)造成死循環(huán),所以并沒(méi)有去進(jìn)行這方面的處理;
寫(xiě),而對(duì)于write, 由于需要寫(xiě)的長(zhǎng)度是已知的,所以可以一直再寫(xiě),直到寫(xiě)完.不過(guò)問(wèn)題是write 是可能被打斷嗎,造成write 一次只write 一部分?jǐn)?shù)據(jù), 所以write 的過(guò)程還是需要考慮循環(huán)write, 只不過(guò)多數(shù)情況下一次write 調(diào)用就可能成功.
非阻塞寫(xiě)的情況下:: //
非阻塞寫(xiě)的情況下,是采用可以寫(xiě)多少就寫(xiě)多少的策略.與讀不一樣的地方在于,有多少讀多少是由網(wǎng)絡(luò)發(fā)送的那一端是否有數(shù)據(jù)傳輸?shù)綖闃?biāo)準(zhǔn),但是對(duì)于可以寫(xiě)多少是由本地的網(wǎng)絡(luò)堵塞情況為標(biāo)準(zhǔn)的,在網(wǎng)絡(luò)阻塞嚴(yán)重的時(shí)候,
網(wǎng)絡(luò)層
沒(méi)有足夠的內(nèi)存來(lái)進(jìn)行寫(xiě)操作,這時(shí)候就會(huì)出現(xiàn)寫(xiě)不成功的情況,阻塞情況下會(huì)盡可能(有可能被中斷)等待到數(shù)據(jù)全部發(fā)送完畢, 對(duì)于非阻塞的情況就是一次寫(xiě)多少算多少,沒(méi)有中斷的情況下也還是會(huì)出現(xiàn)write 到一部分的情況.
如何linux 程序中啟用其他進(jìn)程,非阻塞,非popen
在唯塵兆Linux程序中啟動(dòng)其他進(jìn)程可以用system函數(shù),這個(gè)函數(shù)會(huì)等待它啟動(dòng)的那個(gè)程序結(jié)束才返回,所以它是一個(gè)阻塞調(diào)用。還有一種非阻塞的啟動(dòng)外部程序的方法,指租稍微復(fù)雜一點(diǎn),是運(yùn)用Linux的exec系列函數(shù),之所以說(shuō)系列函數(shù)是因?yàn)橛胁煌淖兎N,只是參數(shù)的形式不同而已,其實(shí)完全是一樣的,exec系列函數(shù)的行為是將當(dāng)前進(jìn)程替換成要啟動(dòng)的那個(gè)新進(jìn)程,這里的當(dāng)前進(jìn)程就是你編寫(xiě)的程序,新進(jìn)程啟動(dòng)后調(diào)用exec函數(shù)的進(jìn)程就不存在了,exec系列函數(shù)調(diào)用之后的代碼也不會(huì)再執(zhí)行了。所以,exec系列函數(shù)的正確使用方法是在程序中進(jìn)行fork調(diào)用復(fù)制進(jìn)程,然后把exec函數(shù)的調(diào)用語(yǔ)句放在fork的子進(jìn)程里面,注兄山意子進(jìn)程中exec函數(shù)調(diào)用的后面就不要寫(xiě)其他功能的代碼了,因?yàn)閑xec函數(shù)后面的語(yǔ)句不會(huì)被執(zhí)行。
關(guān)于linux accept非阻塞的介紹到此就結(jié)束了,不知道你從中找到你需要的信息了嗎 ?如果你還想了解更多這方面的信息,記得收藏關(guān)注本站。
四川成都云服務(wù)器租用托管【創(chuàng)新互聯(lián)】提供各地服務(wù)器租用,電信服務(wù)器托管、移動(dòng)服務(wù)器托管、聯(lián)通服務(wù)器托管,云服務(wù)器虛擬主機(jī)租用。成都機(jī)房托管咨詢(xún):13518219792
創(chuàng)新互聯(lián)(www.cdcxhl.com)擁有10多年的服務(wù)器租用、服務(wù)器托管、云服務(wù)器、虛擬主機(jī)、網(wǎng)站系統(tǒng)開(kāi)發(fā)經(jīng)驗(yàn)、開(kāi)啟建站+互聯(lián)網(wǎng)銷(xiāo)售服務(wù),與企業(yè)客戶共同成長(zhǎng),共創(chuàng)價(jià)值。
網(wǎng)頁(yè)題目:Linux下accept函數(shù)的非阻塞模式(linuxaccept非阻塞)
本文路徑:http://m.5511xx.com/article/cosoeih.html


咨詢(xún)
建站咨詢(xún)
