乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      盤點(diǎn)python socket 中recv函數(shù)的坑...

       昵稱45893186 2022-11-15 發(fā)布于浙江

      1. 首先來(lái)看一下recv函數(shù)的各個(gè)參數(shù)

      函數(shù)原型:int recv( SOCKET s, char *buf, int  len, int flags)

      功能:不論是客戶還是服務(wù)器應(yīng)用程序都用recv函數(shù)從TCP連接的另一端接收數(shù)據(jù)。

      參數(shù)一:指定接收端套接字描述符;

      參數(shù)二:指明一個(gè)緩沖區(qū),該緩沖區(qū)用來(lái)存放recv函數(shù)接收到的數(shù)據(jù);

      參數(shù)三:指明buf的長(zhǎng)度;

      參數(shù)四 :一般置為0。
       

      同步Socket的recv函數(shù)的執(zhí)行流程:當(dāng)應(yīng)用程序調(diào)用recv函數(shù)時(shí),recv先等待s的發(fā)送緩沖中的數(shù)據(jù)被協(xié)議傳送完畢,

      如果協(xié)議在傳送s的發(fā)送緩沖中的數(shù)據(jù)時(shí)出現(xiàn)網(wǎng)絡(luò)錯(cuò)誤,那么recv函數(shù)返回SOCKET_ERROR;

      如果s的發(fā)送緩沖中沒有數(shù)據(jù)或者數(shù)據(jù)被協(xié)議成功發(fā)送完畢后,recv先檢查套接字s的接收緩沖區(qū),如果s接收緩沖區(qū)中沒有數(shù)據(jù)或者協(xié)議正在接收數(shù)據(jù),那么recv就一直等待,直到協(xié)議把數(shù)據(jù)接收完畢;

      當(dāng)協(xié)議把數(shù)據(jù)接收完畢,recv函數(shù)就把s的接收緩沖中的數(shù)據(jù)copy到buf中(注意協(xié)議接收到的數(shù)據(jù)可能大于buf的長(zhǎng)度,所以在這種情況下要調(diào)用幾次recv函數(shù)才能把s的接收緩沖中的數(shù)據(jù)copy完。recv函數(shù)僅僅是copy數(shù)據(jù),真正的接收數(shù)據(jù)是協(xié)議來(lái)完成的),recv函數(shù)返回其實(shí)際copy的字節(jié)數(shù);

      如果recv在copy時(shí)出錯(cuò),那么它返回SOCKET_ERROR;如果recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)網(wǎng)絡(luò)中斷了,那么它返回0。
       

      2.“坑”在哪里,在返回值上,在阻塞與非阻塞上

      要知道,recv函數(shù)是阻塞的,也就是會(huì)一直等待服務(wù)端發(fā)送來(lái)的數(shù)據(jù)包。如果沒有數(shù)據(jù)包到來(lái),就一直會(huì)等待。

      這就直接導(dǎo)致了我用python寫服務(wù)端的時(shí)候出現(xiàn)的一個(gè)解決了很久的錯(cuò)誤,我的代碼很簡(jiǎn)單,就是python服務(wù)端循環(huán)調(diào)用recv函數(shù)接收從客戶端發(fā)來(lái)的一個(gè)文件,如下:

      1. data = connection.recv(1024)
      2. total_data += data
      3. num = len(data)
      4. # 我一開始以為如果沒有數(shù)據(jù)了,讀出來(lái)的data長(zhǎng)度為0,len(data)==0,從而導(dǎo)致卡在while循環(huán)中
      5. while len(data) > 0:
      6. data = connection.recv(1024)
      7. num += len(data)
      8. total_data += data

      而實(shí)際上只有當(dāng)recv函數(shù)在等待協(xié)議接收數(shù)據(jù)時(shí)網(wǎng)絡(luò)中斷了,它才返回0,這就導(dǎo)致我在服務(wù)端一直沒有反應(yīng),等待了很久之后,我將客戶端關(guān)閉之后,出現(xiàn)了結(jié)果,其實(shí)就是這時(shí)候 len(data)=0 了。

      3. 解決方法有哪些呢?

      后來(lái)搜集資料才發(fā)現(xiàn)recv本身是一個(gè)阻塞的,所以可以通過(guò)以下兩種方法,將recv設(shè)置為非阻塞:

      1. socket.setblocking(0)

      2. 使用 socket.MSG_DONTWAIT

      注意將套接字設(shè)置為非阻塞時(shí),可能會(huì)報(bào)一個(gè)錯(cuò):

      WinError 10035 無(wú)法立即完成一個(gè)非阻止性套接字操作

      這個(gè)錯(cuò)誤就是,recv不阻塞了。在 send 數(shù)據(jù)出去后,服務(wù)端還來(lái)沒來(lái)得急返回?cái)?shù)據(jù),客戶端已經(jīng)跑到了recv這里,而又不阻塞,所以拋出了一個(gè)異常。

      要解決這個(gè)問(wèn)題,你需要在每個(gè) recv 函數(shù)前加一句 time.sleep(2),

      其實(shí)還可以通過(guò)設(shè)置 socket.settimeout(5)  即超時(shí)時(shí)間來(lái)改變r(jià)ecv的阻塞狀態(tài),間接地將阻塞狀態(tài)變?yōu)榉亲枞麪顟B(tài)。當(dāng)然,你得確保你的超時(shí)時(shí)間足夠使recv函數(shù)接收完所有的數(shù)據(jù)才行。

      我就是通過(guò)設(shè)置超時(shí)時(shí)間解決了這個(gè)問(wèn)題,你如果也有同樣的問(wèn)題的話,你也可以試試。

      但是設(shè)置超時(shí)在實(shí)際情況中是一個(gè)不是很推薦的方法,后來(lái)在對(duì)socket原理的了解上更改了代碼,解決了這個(gè)問(wèn)題,服務(wù)端把設(shè)置超時(shí)去掉,然后在Android即Java客戶端發(fā)送完所有的數(shù)據(jù)之后,加上如下語(yǔ)句:

      this.socket.shutdownOutput();
      

      就可以解決這個(gè)服務(wù)端阻塞的問(wèn)題。

      最后遇到問(wèn)題,一定要去多看看別人是怎么解決的,多和有經(jīng)驗(yàn)的人交流交流,不然時(shí)間就在糾結(jié)苦惱中溜走了。當(dāng)然,自己首先要進(jìn)行獨(dú)立思考,并將問(wèn)題一步步放小,找到真正的問(wèn)題癥結(jié)所在,再去下手。最后如果問(wèn)題得到解決了,記得分享一下以供更多人參考哦~

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多