none
如何清掉TcpClient 中 Buffer裡面的資料 RRS feed

  • 問題

  • 各位大大

    小弟我利用TcpClient來傳送資料
        Dim Client As New TcpClient
        Dim Stream As NetworkStream

        Stream.Write(S_Out1, 0, S_Out1.Length)
    當我認為回應的資料有問題時,我想要清空Buffer中的資料

    不過卻沒有看到TcpClient中有這個選項

    所以目前做法用LOOP方式利用Read的方式全部讀進來直到確定Client.Available=0
    這個方式好像不是很理想,老實說有點慢

    再次麻煩各位大大了
    2009年10月28日 上午 12:59

解答

  • 你用這樣的程式碼可以一次讀掉 buffer ,但若是別人一直傳,你也只能一直讀,網路傳輸跟時間有關,資料不是瞬間進來的:

    Dim nBuffer As Integer = myTcpClient.ReceiveBufferSize
    Dim tBytes(nBuffer - 1) As Byte
    nBytes = m_NetworkStream.Read(tBytes, 0, nBuffer)



    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    • 已標示為解答 動不了 2009年10月28日 上午 04:59
    2009年10月28日 上午 03:24

所有回覆

  • hi
    嘗試看看
    byte[] buffer=new byte[buffersize] ;//buffer to receive
    Array.Clear(buffer,0,buffer.Length);//clear buffer data 
    http://www.dotblogs.com.tw/ricochen/Default.aspx
    2009年10月28日 上午 01:38

  •     Stream.Write(S_Out1, 0, S_Out1.Length)

    上面這一句就已經把資料送出去了,你還想清空什麼?
    2009年10月28日 上午 01:46
  • 因該是我沒說清楚

    Stream.Write(S_Out1, 0, S_Out1.Length)'<==將資料送出去

    會收到回應值 所以 Client.Available>0

    但是裡面的資料 我不想要

    如果不清空的話 我再用Stream.Write(S_Out1, 0, S_Out1.Length)

    Buffer裡的DATA會越來越多

    2009年10月28日 上午 02:47
  • 讀掉是比較保險的,讀掉你才能安全的控制長度。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年10月28日 上午 03:20
  • 你用這樣的程式碼可以一次讀掉 buffer ,但若是別人一直傳,你也只能一直讀,網路傳輸跟時間有關,資料不是瞬間進來的:

    Dim nBuffer As Integer = myTcpClient.ReceiveBufferSize
    Dim tBytes(nBuffer - 1) As Byte
    nBytes = m_NetworkStream.Read(tBytes, 0, nBuffer)



    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    • 已標示為解答 動不了 2009年10月28日 上午 04:59
    2009年10月28日 上午 03:24
  • 心冷大

    我目前的做法跟您差不多

        Sub ClearBuffer()
            Do
                If Client.Available > 0 Then
                    Dim bytes(Client.Available - 1) As Byte
                    Stream.Read(bytes, 0, Client.Available)
                    Application.DoEvents()
                End If
            Loop Until Client.Available = 0
        End Sub

    原本 我有試過 ReceiveBufferSize=0 暫存區中就會清空
    不過 這樣後變成每次傳送前 都要ReceiveBufferSize=XX
    而且 Client.Available 就會=XX
    如果回應只有10 可是我XX=20 那 Client.Available 卻會=20

    如果ReceiveBufferSize 我完全不去動她  發現他卻是浮動的

    2009年10月28日 上午 03:36
  • ReceiveBufferSize 應該是依據你網路環境來指定,而不是隨意調整,此外大小是不變的,預設為 8 kb。

    1. 網路來的資料寫入 buffer
    2. 從 buffer 讀取資料
    3. 回到 1

    所以要依據這個步驟所需的時間與資料量來計算 Buffer 的大小,若過小,會在 1 等待,若過大只是浪費記憶體。
    假設需時 500 ms (或是你每 500 ms 去讀一次) ,每秒傳輸量為 1 Mbps

    Buffer 的大小:1 * 1024 * 1024 / 8 * 0.5 s = 65,536 bytes = 64 kb

    若加安全系數,你可以設大點,比如說 128 kb ,不然就是設定 64 kb

    但是實際傳進來的,並不會一定剛好滿滿的 buffer 大小,所以你的 byte() 要設定 buffer 大小,而真正在裡面的,是上面程式碼的 nBytes 。

    至於 Available 是參考用,一切以 Read 進來的為準。

    例如使用 Available 到讀取間的微小時差內,剛好遠端傳入 10 bytes 資料:
    1. 得到 Available = 20
    2. 遠端傳進來 10 bytes
    3. 讀取差異:
    a. Stream.Read(bytes, 0, Client.Available) ' 只讀到 20 bytes
    b. nBytes = m_NetworkStream.Read(tBytes, 0, nBuffer) ' 讀到 30 bytes
    4. 遠端再傳進來 8 bytes
    5. Available:
    a. 18 bytes
    b. 8 bytes

    請隨時記住,網路傳輸是動態變化,即時進行。

    還有,
    「每次傳送前 都要ReceiveBufferSize=XX」
    請用詞精確,ReceiveBufferSize 是接收緩衝區,SendBufferSize 才是傳送緩衝區,我不太了解你為何傳送前,是清空接受緩衝區。

    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年10月28日 上午 04:04
  • TcpClinet.Close()不就清掉了嗎 ?
    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    2009年10月28日 上午 04:27
    版主
  • 心冷大大
    不好意思 讓你誤會了

    原本 我有試過 ReceiveBufferSize=0 暫存區中就會清空
    但是如果這時候 送資料過去
    Client.Available 會=0
    ReceiveBufferSize也是=0
    這樣沒辦法接收資料
    所以 每次傳送前 假設我知道回應的BYTE數就需要把ReceiveBufferSize=回應BYTE數

    Bill Chung大
    TcpClinet.Close 是清掉了
    不過當我在從新建立連線 暫存區的資料還是會在

    目前 改用心冷大提供的方法

    2009年10月28日 上午 04:58
  • ReceiveBufferSize=0 這算是修改緩衝區大小為 0 ,雖然有清空的意義,但是一般不會叫做清空,因為緩衝區大小為 0 後,資料就傳不進來,到你下次恢復原來大小的期間,資料都收不到。

    資料收不到,當然 Available 就會是 0 ,因為 Available 永遠 <= ReceiveBufferSize

    除了因為高速網路環境下調整外,程式碼中不該動緩衝區大小。
    所以你這段觀念還是錯:
    「所以 每次傳送前 假設我知道回應的BYTE數就需要把ReceiveBufferSize=回應BYTE數」

    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年10月28日 上午 08:16
  • 舉個比較容易理解的例子:

    目標:把硬碟內容清空。

    可能方法選擇:
    1. 買一顆新硬碟來重做。 (New TcpClient)
    2. 用 FDISK 重做。(TcpClient.Close)
    3. 用 Format 重做。(ReceiveBufferSize = 0)
    4. 用刪除指令將檔案刪除。(用程式碼讀掉)

    一般理解的意思應該是 4 。

    括號內是類比到你的問題。
    一般不會選擇 1 ~ 3 的方法,除非你很明確知道你在幹什麼。


    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年10月28日 上午 08:22
  • 心冷大 我瞭解妳的意思

    所以 每次傳送前 假設我知道回應的BYTE數就需要把ReceiveBufferSize=回應BYTE數<===這個只是我一個測試過程

    最後 我還是使用你的方法將我那個 FUNCTION小小修改一下

    1. 買一顆新硬碟來重做。 (New TcpClient)
    2. 用 FDISK 重做。(TcpClient.Close)
    3. 用 Format 重做。(ReceiveBufferSize = 0)
    4. 用刪除指令將檔案刪除。(用程式碼讀掉)

    上面這四種方法 我都試過

    最後才選用第四種

    2009年10月28日 上午 08:31