回覆列表
  • 1 # 使用者9937787127551

      還有就是用recv讀取,但是由於不知道快取裡有多少資料,如果是阻塞模式,到最後必然等到超時才知道資料已經讀取完畢,這是個問題。   另一個是用fgetc,透過返回判斷是否是feof:   whlie (1) { a=fgetc(f);if (feof(f)) break;//   b=fgetc(f);if (feof(f)) break;//  }  當然,我不知道讀取完畢後最後一次呼叫fgetc會不會堵塞,需要測試。   在非阻塞模式下,我們用recv就可以輕鬆搞定了,但是阻塞模式下,由於我們不知道緩衝區有多少資料,不能直接呼叫recv嘗試清除。   使用一個小小的技巧,利用select函式,我們可以輕鬆搞定這個問題:   select函式用於監視一個檔案描述符集合,如果集合中的描述符沒有變化,則一直阻塞在這裡,直到超時時間到達;在超時時間內,一旦某個描述符觸發了你所關心的事件,select立即返回,透過檢索檔案描述符集合處理相應事件;select函數出錯則返回小於零的值,如果有事件觸發,則返回觸發事件的描述符個數;如果超時,返回0,即沒有資料可讀。   重點在於:我們可以用select的超時特性,將超時時間設定為0,透過檢測select的返回值,就可以判斷緩衝是否被清空。透過這個技巧,使一個阻塞的socket成了‘非阻塞’socket.   現在就可以得出解決方案了:使用select函式來監視要清空的socket描述符,並把超時時間設定為0,每次讀取一個位元組然後丟棄(或者按照業務需要進行處理,隨你便了),一旦select返回0,說明緩衝區沒資料了(超時了)。   struct timeval tmOut;tmOut.tv_sec = 0;tmOut.tv_usec = 0;fd_set fds;FD_ZEROS(&fds);FD_SET(skt, &fds);   int nRet;   char tmp[2];   memset(tmp, 0, sizeof(tmp));   while(1)   { nRet= select(FD_SETSIZE, &fds, NULL, NULL, &tmOut);if(nRet== 0) break;recv(skt, tmp, 1,0);}   這種方式的好處是,不再需要用recv、recvfrom等阻塞函式直接去讀取,而是使用select,利用其超時特性檢測緩衝區是否為空來判斷是否有資料,有資料時才呼叫recv進行清除。   有人說同樣可以用recv和socket的超時設定去清空啊,這個沒錯,但是你需要直接對socket描述符設定超時時間,而為了清空資料而直接修改socket描述符的屬性,可能會影響到其他地方的使用,造成系統奇奇怪怪的問題,所以,不推薦使用。

  • 中秋節和大豐收的關聯?
  • 如何處理同事之間的那些因經濟產生的矛盾?