none
無線socket傳輸的問題 RRS feed

  • 問題

  •  

    小弟我在寫一個 client 向 server 上傳 file 的程式

    在server端每收到一個封包   就sleep(10)

    可是有的時候網路狀況比較不好 沒有辦法收到完整的封包

    例如接收端收到的封包大小應該是 1025 bytes   可是網路狀況不好的時候可能會出現在400~500之間

    這時候傳輸的檔案 就會發生問題

    小弟我嘗試將sleep的時間調大   發生傳輸失敗的機會就變小了 但是整體傳輸也會變慢很多

    請問有沒有辦法解決這樣的問題呢

     

     

    SERVER端程式

            Dim listener As New Socket(AddressFamily.InterNetwork, _
                SocketType.Stream, ProtocolType.Tcp)

            listener.Bind(localEndPoint)
            listener.Listen(10)
            Dim fs As New IO.FileStream("filename", FileMode.Create)
            Dim w As New IO.BinaryWriter(fs)
               Dim handler As Socket = listener.Accept()
               data = Nothing
                While True
                    bytes = New Byte(1024) {}
                    Dim bytesRec As Integer = handler.Receive(bytes)
                    w.Write(bytes)

                    data = Encoding.ASCII.GetString(bytes, 0, bytesRec)
                    
                    Threading.Thread.Sleep(10)

                    '看有沒有收到代表結束的封包(EOF)
                    If data.IndexOf("<EOF>") > -1 Then
                        Console.WriteLine("Text received : {0}", data)
                        Exit While

                    Else
                        data = Nothing
                    End If
                End While


    Client 端程式

               sender.Send("真正要傳的file")

               Dim msg2 As Byte() = _
                           Encoding.ASCII.GetBytes("This is a test<EOF>")
                Dim bytesSent2 As Integer = sender.Send(msg2) 

               '多傳一次表示結束

      

    2008年7月21日 下午 02:40

解答

  • 1. 在區網內要把 Buffer 加大,預設 8 kb ,假設你是 54M 的無線網路,則每秒 6.75 MB,每 10 毫秒存取一次,是 67 kb 。我自己是慣用512 kb 。

     

    2. 你既然知道 bytesRec 的用途,在下面這句使用:

    Code Snippet

    data = Encoding.ASCII.GetString(bytes, 0, bytesRec)

     

     

    那下面這句怎麼不用 bytesRec ?

    Code Snippet

    w.Write(bytes)

     

     

    3. 網路傳輸你無法預期跑程式碼時,收到哪些東西,要是 <EOF> 字串剛好分在兩次傳時,你的程式不是永遠都結束不了?

     

     

    我會建議傳輸時,每 32kb 一切,先傳位元組大小,再傳 32 kb ,正確收到時回應給 client 端,比如說傳回 1 表示完成,0 表示重傳,再由 client 來處理續傳或重傳,這樣程式碼是用位元組數來算,就不要用字串判讀。

    2008年7月21日 下午 05:32
    版主

所有回覆

  • 1. 在區網內要把 Buffer 加大,預設 8 kb ,假設你是 54M 的無線網路,則每秒 6.75 MB,每 10 毫秒存取一次,是 67 kb 。我自己是慣用512 kb 。

     

    2. 你既然知道 bytesRec 的用途,在下面這句使用:

    Code Snippet

    data = Encoding.ASCII.GetString(bytes, 0, bytesRec)

     

     

    那下面這句怎麼不用 bytesRec ?

    Code Snippet

    w.Write(bytes)

     

     

    3. 網路傳輸你無法預期跑程式碼時,收到哪些東西,要是 <EOF> 字串剛好分在兩次傳時,你的程式不是永遠都結束不了?

     

     

    我會建議傳輸時,每 32kb 一切,先傳位元組大小,再傳 32 kb ,正確收到時回應給 client 端,比如說傳回 1 表示完成,0 表示重傳,再由 client 來處理續傳或重傳,這樣程式碼是用位元組數來算,就不要用字串判讀。

    2008年7月21日 下午 05:32
    版主
  •  璉璉 寫信:

    1. 在區網內要把 Buffer 加大,預設 8 kb ,假設你是 54M 的無線網路,則每秒 6.75 MB,每 10 毫秒存取一次,是 67 kb 。我自己是慣用512 kb 。

     

    2. 你既然知道 bytesRec 的用途,在下面這句使用:

    Code Snippet

    data = Encoding.ASCII.GetString(bytes, 0, bytesRec)

     

     

    那下面這句怎麼不用 bytesRec ?

    Code Snippet

    w.Write(bytes)

     

     

    3. 網路傳輸你無法預期跑程式碼時,收到哪些東西,要是 <EOF> 字串剛好分在兩次傳時,你的程式不是永遠都結束不了?

     

     

    我會建議傳輸時,每 32kb 一切,先傳位元組大小,再傳 32 kb ,正確收到時回應給 client 端,比如說傳回 1 表示完成,0 表示重傳,再由 client 來處理續傳或重傳,這樣程式碼是用位元組數來算,就不要用字串判讀。

     

    參考了你前兩項的建議  目前我的傳輸就算是沒有辦法接收到完整的封包  也不至於會錯 誤了

    至於第三項建議小弟我功力尚淺 一直沒有辦法寫出沒有 bug 的版本

    我在想如果我在 傳輸 <EOF> 字串的前  先 sleep(500)

    是否就可以順利避開你說的  <EOF> 剛好分在兩次傳輸的情況呢  謝謝

    2008年7月22日 上午 09:47
  • 你不能預期何時會傳回 <EOF> ,所以你也不知道何時該 Sleep(500) 啊~

     

    如果是把每次的傳輸都改為 Sleep(500) ,結果問題還是存在,只是發生機率會變小 50 倍 (500/10)。

    2008年7月22日 上午 09:52
    版主
  •  璉璉 寫信:

    你不能預期何時會傳回 <EOF> ,所以你也不知道何時該 Sleep(500) 啊~

     

    如果是把每次的傳輸都改為 Sleep(500) ,結果問題還是存在,只是發生機率會變小 50 倍 (500/10)。

     

    不好意思可能我沒有講清楚讓你誤會了

    我是client要傳輸檔案到 server 端

    client  先 send("file")之後 會 send(<EOF>)

     

    server方面的判斷是收到  <EOF> 的封包後   斷開連線

     

    如果我 client先 send("file") -> sleep(500) -> send (<EOF>)

     

     這樣的話   server 端就比較不會有判斷錯誤的發生

    請問我這樣想有錯誤嗎  謝謝
    2008年7月22日 上午 09:58
  • 看不懂你的意思,除非你有定義交談的方式,否則網路傳輸即使你分多次傳,接收端還是持續收到。

     

    從你既有的程式碼來看,你 Server 端並沒有傳送任何訊息給 client 端,所以可以說是沒有任何交談的定義。

     

    假設你連續傳輸 "file" "<EOF>" ,Server 會收到 "file<EOF>",並不一定會分兩次收到,看網路頻寬跟讀取頻率,所以你的描述讓人更看不懂。

    2008年7月22日 上午 10:04
    版主