新聞中心
recv是阻塞還是非阻塞的?
socket分為阻塞和非阻塞兩種,可以通過setsockopt,或者更簡單的setblocking, settimeout設(shè)置。

成都創(chuàng)新互聯(lián)是一家集網(wǎng)站建設(shè),羅莊企業(yè)網(wǎng)站建設(shè),羅莊品牌網(wǎng)站建設(shè),網(wǎng)站定制,羅莊網(wǎng)站建設(shè)報(bào)價(jià),網(wǎng)絡(luò)營銷,網(wǎng)絡(luò)優(yōu)化,羅莊網(wǎng)站推廣為一體的創(chuàng)新建站企業(yè),幫助傳統(tǒng)企業(yè)提升企業(yè)形象加強(qiáng)企業(yè)競爭力。可充分滿足這一群體相比中小企業(yè)更為豐富、高端、多元的互聯(lián)網(wǎng)需求。同時(shí)我們時(shí)刻保持專業(yè)、時(shí)尚、前沿,時(shí)刻以成就客戶成長自我,堅(jiān)持不斷學(xué)習(xí)、思考、沉淀、凈化自己,讓我們?yōu)楦嗟钠髽I(yè)打造出實(shí)用型網(wǎng)站。
阻塞式的socket的recv服從這樣的規(guī)則:當(dāng)緩沖區(qū)內(nèi)有數(shù)據(jù)時(shí),立即返回所有的數(shù)據(jù);當(dāng)緩沖區(qū)內(nèi)無數(shù)據(jù)時(shí),阻塞直到緩沖區(qū)中有數(shù)據(jù)。
非阻塞式的socket的recv服從的規(guī)則則是:當(dāng)緩沖區(qū)內(nèi)有數(shù)據(jù)時(shí),立即返回所有的數(shù)據(jù);當(dāng)緩沖區(qū)內(nèi)無數(shù)據(jù)時(shí),產(chǎn)生EAGAIN的錯(cuò)誤并返回(在Python中會(huì)拋出一個(gè)異常)。
兩種情況都不會(huì)返回空字符串,返回空數(shù)據(jù)的結(jié)果是對(duì)方關(guān)閉了連接之后才會(huì)出現(xiàn)的。由于TCP的socket是一個(gè)流,因此是不存在“讀完了對(duì)方發(fā)送來的數(shù)據(jù)”這件事的。
你必須要每次讀到數(shù)據(jù)之后,根據(jù)數(shù)據(jù)本身來判斷當(dāng)前需要等待的數(shù)據(jù)是否已經(jīng)全部收到,來判斷是否進(jìn)行下一個(gè)recv。
可以看一下hiredis庫的接口設(shè)計(jì),hiredis中的Reader有兩個(gè)接口,分別是feed和gets,feed每次送入一部分?jǐn)?shù)據(jù),不需要保證是正確分片的;gets則返回已經(jīng)得到的完整的結(jié)果,如果返回False,表示已經(jīng)沒有新的結(jié)果。基本上所有的TCP的socket編程都是遵循這樣的方法:讀入新數(shù)據(jù);判斷有沒有完整的新消息;處理新消息,或者等待更多數(shù)據(jù)。
網(wǎng)絡(luò)編程中阻塞和非阻塞socket的區(qū)別?
阻塞:一般的I/O操作可以在新建的流中運(yùn)用.在服務(wù)器回應(yīng)前它等待客戶端發(fā)送一個(gè)空白的行.當(dāng)會(huì)話結(jié)束時(shí),服務(wù)器關(guān)閉流和客戶端socket.如果在隊(duì)列中沒有請(qǐng)示將會(huì)出現(xiàn)什么情況呢?那個(gè)方法將會(huì)等待一個(gè)的到來.這個(gè)行為叫阻塞.accept()方法將會(huì)阻塞服務(wù)器線程直到一個(gè)呼叫到來.當(dāng)5個(gè)連接處理完閉之后,服務(wù)器退出.任何的在隊(duì)列中的呼叫將會(huì)被取消.
非阻塞:非阻塞套接字是指執(zhí)行此套接字的網(wǎng)絡(luò)調(diào)用時(shí),不管是否執(zhí)行成功,都立即返回。比如調(diào)用recv()函數(shù)讀取網(wǎng)絡(luò)緩沖區(qū)中數(shù)據(jù),不管是否讀到數(shù)據(jù)都立即返回,而不會(huì)一直掛在此函數(shù)調(diào)用上。在實(shí)際Windows網(wǎng)絡(luò)通信軟件開發(fā)中,異步非阻塞套接字是用的最多的。平常所說的C/S(客戶端/服務(wù)器)結(jié)構(gòu)的軟件就是異步非阻塞模式的
如何解決socket阻塞?
由于socket是以數(shù)據(jù)流的形式發(fā)送數(shù)據(jù),接收方不知道對(duì)方一次性發(fā)送了多少數(shù)據(jù),也能保證對(duì)方一次性發(fā)送的數(shù)據(jù)能在同一刻接收到,所以Receive方法是這么工作的:
接受一個(gè)byye[]類型的參數(shù)作為緩沖區(qū),在經(jīng)過一定的時(shí)間后把接收到的數(shù)據(jù)填充到這個(gè)緩沖區(qū)里面,并且返回實(shí)際接收到數(shù)據(jù)的長度,這個(gè)實(shí)際接收到的數(shù)據(jù)長度有可能為0(沒有接收到數(shù)據(jù))、大于0小于緩沖區(qū)的長度(接收到數(shù)據(jù),但是沒有我們預(yù)期的多)、等于緩沖區(qū)的長度(說明接收到的數(shù)據(jù)大于等于我們預(yù)期的長度)。
每次接收緩沖區(qū)都用同一個(gè)byte[]byteMessage,并且你沒有檢查接收到的數(shù)據(jù)長度,所以第一次你接收到的數(shù)據(jù)是123456,第二次你只接收到了8,但是緩沖區(qū)里面還有23456,所以加起來就是823456了。
socket接收緩沖區(qū)的大小有講究,設(shè)置大了接收起來慢,因?yàn)樗缺M可能多的數(shù)據(jù)接收到了再返回;設(shè)置小了需要重復(fù)多次調(diào)用接收方法才能把數(shù)據(jù)接收完,socket有個(gè)屬性,標(biāo)識(shí)了系統(tǒng)默認(rèn)的接收緩沖區(qū)大小,可以參考這個(gè)!
還有就是用recv讀取,但是由于不知道緩存里有多少數(shù)據(jù),如果是阻塞模式,到最后必然等到超時(shí)才知道數(shù)據(jù)已經(jīng)讀取完畢,這是個(gè)問題。
另一個(gè)是用fgetc,通過返回判斷是否是feof:
whlie(1){a=fgetc(f);if(feof(f))break;//…
b=fgetc(f);if(feof(f))break;//… } 當(dāng)然,我不知道讀取完畢后最后一次調(diào)用fgetc會(huì)不會(huì)堵塞,需要測(cè)試。
到此,以上就是小編對(duì)于Windows非阻塞send返回值的問題就介紹到這了,希望這3點(diǎn)解答對(duì)大家有用。
網(wǎng)頁標(biāo)題:recv是阻塞還是非阻塞的?windows非阻塞recv
網(wǎng)站鏈接:http://www.5511xx.com/article/coedhih.html


咨詢
建站咨詢
