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


咨詢
建站咨詢
