清空socket快取區的資料的方法由於socket是以資料流的形式傳送資料,接收方不知道對方一次性發送了多少資料,也能保證對方一次性發送的資料能在同一刻接收到,所以Receive方法是這麼工作的:接受一個byye[]型別的引數作為緩衝區,在經過一定的時間後把接收到的資料填充到這個緩衝區裡面,並且返回實際接收到資料的長度,這個實際接收到的資料長度有可能為0(沒有接收到資料)、大於0小於緩衝區的長度(接收到資料,但是沒有我們預期的多)、等於緩衝區的長度(說明接收到的資料大於等於我們預期的長度)。每次接收緩衝區都用同一個byte[]byteMessage,並且你沒有檢查接收到的資料長度,所以第一次你接收到的資料是123456,第二次你只接收到了8,但是緩衝區裡面還有23456,所以加起來就是823456了。socket接收緩衝區的大小有講究,設定大了接收起來慢,因為它要等儘可能多的資料接收到了再返回;設定小了需要重複多次呼叫接收方法才能把資料接收完,socket有個屬性,標識了系統預設的接收緩衝區大小,可以參考這個! 還有就是用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,說明緩衝區沒資料了(“超時”了)。
清空socket快取區的資料的方法由於socket是以資料流的形式傳送資料,接收方不知道對方一次性發送了多少資料,也能保證對方一次性發送的資料能在同一刻接收到,所以Receive方法是這麼工作的:接受一個byye[]型別的引數作為緩衝區,在經過一定的時間後把接收到的資料填充到這個緩衝區裡面,並且返回實際接收到資料的長度,這個實際接收到的資料長度有可能為0(沒有接收到資料)、大於0小於緩衝區的長度(接收到資料,但是沒有我們預期的多)、等於緩衝區的長度(說明接收到的資料大於等於我們預期的長度)。每次接收緩衝區都用同一個byte[]byteMessage,並且你沒有檢查接收到的資料長度,所以第一次你接收到的資料是123456,第二次你只接收到了8,但是緩衝區裡面還有23456,所以加起來就是823456了。socket接收緩衝區的大小有講究,設定大了接收起來慢,因為它要等儘可能多的資料接收到了再返回;設定小了需要重複多次呼叫接收方法才能把資料接收完,socket有個屬性,標識了系統預設的接收緩衝區大小,可以參考這個! 還有就是用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,說明緩衝區沒資料了(“超時”了)。