1. <nobr id="easjo"><address id="easjo"></address></nobr>

      <track id="easjo"><source id="easjo"></source></track>
      1. 
        

      2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
      3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>
          貴州做網站公司
          貴州做網站公司~專業!靠譜!
          10年網站模板開發經驗,熟悉國內外開源網站程序,包括DEDECMS,WordPress,ZBlog,Discuz! 等網站程序,可為您提供網站建設,網站克隆,仿站,網頁設計,網站制作,網站推廣優化等服務。我們專注高端營銷型網站,企業官網,集團官網,自適應網站,手機網站,網絡營銷,網站優化,網站服務器環境搭建以及托管運維等。為客戶提供一站式網站解決方案?。?!

          【原創】通過 ioctl + FIONREAD 判定數據可讀「建議收藏」

          來源:互聯網轉載 時間:2024-01-29 07:46:46

          【原創】通過 ioctl + FIONREAD 判定數據可讀

          摩云飛 2016-05-12 09:57:51 瀏覽470 評論0

          libevent ioctl FIONREAD

          摘要: 在排查業務 bug 的過程中,看到如下兩種輸出信息: TCP 連接正常情況下,進行數據讀取 14:00:38 epoll_ctl(26, EPOLL_CTL_MOD, 31, {EPOLLIN, {u32=31, u64=31}}) = 0 14:00:38 epoll_wait(26, { {EP

          在排查業務 bug 的過程中,看到如下兩種輸出信息: TCP 連接正常情況下,進行數據讀取

          14:00:38 epoll_ctl(26, EPOLL_CTL_MOD, 31, {EPOLLIN, {u32=31, u64=31}}) = 014:00:38 epoll_wait(26, {      {EPOLLIN, {u32=31, u64=31}}}, 32, 9698) = 114:00:38 clock_gettime(CLOCK_MONOTONIC, {      152386, 122371397}) = 014:00:38 gettimeofday({      1445666438, 713982}, NULL) = 014:00:38 ioctl(31, FIONREAD, [16])      = 014:00:38 readv(31, [{      "224Vx3", 16}], 1) = 16

          TCP 連接斷開情況下(人為強制斷開),進行數據讀取

          14:00:38 epoll_ctl(26, EPOLL_CTL_ADD, 31, {      EPOLLIN, {u32=31, u64=31}}) = 014:00:38 epoll_wait(26, {      {      EPOLLIN, {u32=31, u64=31}}}, 32, 10000) = 114:00:43 clock_gettime(CLOCK_MONOTONIC, {      152390, 497764210}) = 014:00:43 gettimeofday({      1445666443, 89440}, NULL) = 0發現此時 socket 中可讀數據為 0 14:00:43 ioctl(31, FIONREAD, [0])       = 0這里會看到一些亂七八糟的數據(應該是由于 readv 用于保存讀取結果的 buffer 沒有清空的緣故)14:00:43 readv(31, [{      "[pid]:25002 [UpuWrapper]: [UpuClientMsgCallBack] ClientSeesion:0x94f50f8 recive upu result msg:3, result type:0, nResultCount:0 n2@320W371102@320W@320Wdows","status":"callidle","nuaddr":"172.16.185.135","mtaddr":"172.16.72.105","userdomain":"0q0y1aphxubof8ycru6fsgsk","devid":"10103000000002000000000000000002","data":""}]10223172/localtime10220172domain0005 2$008f320W10130010320W@2,34010320Wh2,350f320Wnhv320W1Df320W4v320Wn2202004270t320W4v320W344n320W344n320W|n320W4n320WTt320WTt320W37410320W37410320W201@320W@320W20,260f320W4n320W204f320W250n320W2prototype001I200320W200320W0000002000000000000000002"ff"@3004c52a-deb2-499c-add5-db70f1f62bff3162@320Wx6320W2000410t320Wc52a-deb2-499c-add5-db70f1f62bff33152x6320W8t320Wmoid)Hv320Wx6320W203420010320W110000423H$(v320W4v320W"..., 4096}], 1) = 0

          兩種情況的對比圖如下(為了顯示方便,右側圖中多余數據已刪除)

          由圖中所示,可以得到如下結論:

          • ioctl 能夠判定 socket 緩沖區中可讀數據的數量,兩種情況下 ioctl 調用都返回 0 ,即成功。
          • readv 在兩種情況都進行了數據讀取,TCP 鏈路正常情況下,readv 返回讀取的數據字節數;TCP 鏈路異常情況下,readv 返回 0 。

          libevent 中的對應代碼實現如下:

          按理說,這個問題到這里應該算結束了,但是不幸的是,我又搜到了下面這個帖子: === 我是瑯琊榜的分隔線 === Linux – ioctl with FIONREAD always 0 問題: I’m trying to get to know how many bytes there are readable at my TCP socket. I am calling ioctl with the Flag “FIONREAD” which should actually give me this value. When I call the function I get as return val 0 ( so no Error ) but also my integer argument gets the value 0. That would be no problem but when I call the recv() method I actually read some Bytes out of the socket. What am I doing wrong? 嘗試獲取 TCP socket 上有多少字節數據可讀,調用使用 ioctl 配合 FIONREAD 進行獲取。當調用 ioctl 后得到返回值 0 表明沒有錯誤發生,但是保存當前可讀字節數量的變量內容同樣為 0 。這種情況數據正常行為,但是當代碼中實際執行 recv() 調用時,發現能夠從當前 socket 上讀出若干字節來。哪里有問題呢?

          // here some Code: char recBuffer[BUFFERLENGTH] = {     0}; int bytesAv = 0; int bytesRead = 0; int flags = 0; if ( ioctl (m_Socket,FIONREAD,&bytesAv) < 0 ) { // Error } if ( bytesAv < 1 ) { // No Data Available } bytesRead = recv(m_Socket,recBuffer,BUFFERLENGTH,flags);

          When I call the recv function i acutally read some valid Data ( which I expected ) 有人回答如下: The real answer here is to use select(2) like cnicutar said. Toby, what you aren’t understanding is that you have a race condition. First you look at the socket and ask how many bytes are there. Then, while your code is processing the “no data here” block, bytes are being received by the hardware & OS asynchronous to your application. So, by the time that the recv() function is called, the answer of “no bytes are available” is no longer true… 問題的真正原因是,上述代碼調用存在競爭問題。首先,你通過調用 ioctl 查看 socket 中是否存在可讀字節,再你查看的那該時刻,可能恰好確實沒有數據可讀;而之后,在代碼進行“無數據存在”邏輯處理時,可能已經經由硬件和操作系統異步的向應用程序傳輸數據了。所以,當代碼執行到 recv() 函數時,“無數據存在”這個結論可能已經不正確了。

          if ( ioctl (m_Socket,FIONREAD,&bytesAv) < 0 ) { // Error  } // BYTES MIGHT BE RECEIVED BY HARDWARE/OS HERE! if ( bytesAv < 1 ) // AND HERE! { // No Data Available // BUT BYTES MIGHT BE RECEIVED BY HARDWARE/OS HERE! } // AND MORE BYTES MIGHT BE RECEIVED BY HARDWARE/OS HERE! bytesRead = recv(m_Socket,recBuffer,BUFFERLENGTH,flags); // AND NOW bytesRead IS NOT EQUAL TO 0!

          Sure, a small sleep probably fixed your program two years ago, but it also taught you terrible coding practice and you lost out on an opportunity to learn how to use sockets correctly by using select(). 通過調用 sleep 進行短暫的休眠可以簡單粗暴的修復次問題,但是這絕非正確的編程實踐,正確的作為應該是基于 select 進行處理。 Further, as Karoly Horvath said, you can tell recv to not read more bytes than you can store in the buffer that the user passed in. Then your function interface becomes “This fn will return as many bytes as are available on the socket, but not more than [buffer size you passed in]”. 更進一步,你可以令 recv() 至多讀取指定 buffer 長度的數據,故函數接口行為就變成了“該函數將返回當前 socket 上可讀盡可能多的數據,但是不超過傳入 buffer 的長度”。 This means that this function doesn’t need to worry about clearing the buffer any more. The caller can call your function as many times as necessary to clear all of the bytes out of it (or you can provide a separate fn that discards the data wholesale and not tie up that functionality in any specific data gather function). Your function is more flexible by not doing too many things. You can then create a wrapper function that is smart to your data transfer needs of a particular application, and that fn calls the get_data fn and the clear_socket fn as needed for that specific app. Now you are building a library you can carry around from project to project, and maybe job to job if you’re so lucky as to have an employer that lets you take code with you. 這就意味著,該函數將不再需要擔心 buffer 內容清除的問題。調用者可以任意次數調用該函數,因為其自帶數據清除效果(或者你可以提供單獨的函數進行數據清除動作,而不將此功能綁定到任何特定的數據獲取函數上)。你的函數將更加靈活,因為其不用負責過多工作。你可以創建一個更符合你要的封裝函數,以針對特定應用中數據傳輸的需要,而該封裝函數內部會調用 get_data 和 clear_socket 函數進行相應處理。通過這種方式,你就可以得到一個可以在各種工程中隨意使用的庫了。 === 我是瑯琊榜的分隔線 === 乍一看,似乎帖子中描述的情況和上面 TCP 鏈路斷開時的情況類似,但事實上是不同的,關鍵在于 readv 的返回值為 0 ,至于 readv 第二個參數 const struct iovec *iov 的內容,實際為 IOV_TYPE vecs[0] 所指向內存地址中的內容,并非從 socket 上讀取的內容。 至于 libevent 中使用 ioctl 時是否存在 race condition 問題,其實多慮了,提供代碼片段如下:

          版權聲明:本文內容由互聯網用戶自發貢獻,本社區不擁有所有權,也不承擔相關法律責任。如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: yqgroup@service.aliyun.com 進行舉報,并提供相關證據,一經查實,本社區將立刻刪除涉嫌侵權內容。

          163627.html

          標簽:fionread-

          網絡推廣與網站優化公司(網絡優化與推廣專家)作為數字營銷領域的核心服務提供方,其價值在于通過技術手段與策略規劃幫助企業提升線上曝光度、用戶轉化率及品牌影響力。這...

          在當今數字化時代,公司網站已成為企業展示形象、傳遞信息和開展業務的重要平臺。然而,對于許多公司來說,網站建設的價格是一個關鍵考量因素。本文將圍繞“公司網站建設價...

          在當今的數字化時代,企業網站已成為企業展示形象、吸引客戶和開展業務的重要平臺。然而,對于許多中小企業來說,高昂的網站建設費用可能會成為其發展的瓶頸。幸運的是,隨...

          OPPOa57能賣多少?oppoa57二手手機能賣到2800元。oppoa57現在能回收多少錢?OPPOa57現在能可以回收的價錢是大約150元錢左右。oppoa57和a96哪個好?這個是OPPO a96更合適的,畢竟a96的芯片是聯發科天機900,而a57的芯片只能天機720,運行速度上A96要比a五七不運行的更好的。oppoa57是幾g網絡手機?OPPOA57有全網通版本和天翼定制版本。A57...

          中國移動CMCC無線WIFI免費使用步驟?CMCC無線WIFI免費使用步驟1.打開手機,點擊【設置】選項,然后點擊【無線局域網】選項進入無線局域網頁面。選擇【CMCC-FR怎樣使用移動cmcc的wifi熱點? s CMCC無線局域網每個月可以免費使用10個小時,網速很快。如果能找到信號,可以嘗試連接。具體連接方法如下:1.首先搜索出信號【CMCC-FR如何連接CMCC的WiFi?1.確定你已經在營...

          ctite和ctnet那個快?Ctlte是中國電信的4G接入點。就像cmwap和cmnet一樣,只有通過這個接入點才能使用中國電信的4G網絡。Ctnet(wireless broadband):定義:指用戶在手機上設置卡片或Ctnet賬號接入互聯網,或PC機通過手機數據線接入互聯網,主要為PC機、筆記本電腦、PDA等提供GPRS互聯網接入服務,等等兩個服務對象不同,沒有可比性。一般來說,ctlte...

          TOP
          国产初高中生视频在线观看|亚洲一区中文|久久亚洲欧美国产精品|黄色网站入口免费进人
          1. <nobr id="easjo"><address id="easjo"></address></nobr>

              <track id="easjo"><source id="easjo"></source></track>
              1. 
                

              2. <bdo id="easjo"><optgroup id="easjo"></optgroup></bdo>
              3. <track id="easjo"><source id="easjo"><em id="easjo"></em></source></track><option id="easjo"><span id="easjo"><em id="easjo"></em></span></option>