none
c# socket 的問題 RRS feed

  • 問題

  • 請問一下 我在 c# 中 用TCP 的Socket 傳資料
    socket.send 給 "接收端" 而 接收端用 socket.receive 收
    若資料很大 就我所知應該會拆成好幾個 封包傳送
    若 "傳送端" 連續傳送 封包順序可能會不一致
    這樣會不會 造成 接收端 receive 的順序會變得不一致

    我的想法是 : 當"傳送端"送出 很大的資料 "接收端" 會等把資料收齊 才算  "一次" receive

                     然後才接下一個send 送出的的資料
                     至於傳送順序 就是按 傳送端 傳送的順序 不知這樣對不對?!

    另外 UDP 跟 TCP 是否也是一樣的機制 只差在 不一定保證資料傳送到 ?!

    2010年9月14日 下午 03:55

解答

  • 假設 A 傳給 B, 一般會設計類似這樣的機制

    (1) A --啟始訊號--> B

    (2) B--確認已收到啟始訊號, 請開始傳送-->A

    (3) A--傳送真正的Data-->B

    (4) B--傳送已接收完畢訊號-->A

    (5) 繼續下一輪

    另一個關於執行個體的問題, 上文所提連結中有一段

    myTcpListener = New TcpListener(IPAddress.Any, iPort)

                Dim ClientSocket As Socket
                myTcpListener.Start()

                Do
                    ClientSocket = myTcpListener.AcceptSocket()
                    If ClientSocket.Connected = True Then
                          Dim myObj As New CSState
                        myObj.myTcpListener = myTcpListener
                        myObj.ClientSocket = ClientSocket
                        myObj.mystring = Now.ToString("yyyy/MM/dd HH:mm:ss") & "已連線"
                        DisplayMsg1(myObj)
                        Dim ReceiveThread As New Thread(AddressOf ReceiveData)
                        ReceiveThread.IsBackground = True
                        ReceiveThread.Start(myObj)
                        iCount += 1
                    End If
                Loop

    這邊之所以一定要產生一個新的CSState執行個體再拋給Receive程序的原因就在於不要讓兩個不同遠端對象指向同一個記憶體空間造成混亂.

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    • 已標示為解答 布利 2010年9月18日 上午 03:13
    2010年9月15日 上午 04:12
    版主
  • 這和程式的目的有關吧 ? 如果你的設計要確保資料的正確, 就必須自己設計一些控制.

    實做流程是

    Server B -> Start Listen

    PC A --> Connect To Server B

    PCA  --> Send 一個自訂的啟始訊號 To Server B

    Server B receive 啟始訊號, 確認封包內容無誤, Send 確認啟始給PC A

    PC A receive 確認啟始, Send 要傳送的Data to Server B

    Server B receive Data, 直到接收完畢 , Send 自訂的結束訊號給 PC A

    PC A receive 自訂結束訊號, Close Socket,


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    • 已標示為解答 布利 2010年9月18日 上午 03:13
    2010年9月15日 上午 07:33
    版主
  • FAQ

    本站有相當多的討論與程式碼:

    http://www.google.com.tw/search?hl=zh-TW&source=hp&q=TcpClient%7CSocket+%E6%8E%A5%E6%94%B6+%E8%BF%B4%E5%9C%88+site%3Asocial.msdn.microsoft.com%2FForums%2Fzh-TW%2F&aq=f

    我的建議是傳 byte() ,先傳長度,傳 byte() 就可以壓縮、加密,也不受語系限制而變亂碼。

    RFC 裡面一堆通訊協定的確用換行來分隔,但是我覺得這樣滿爛的,還不如先傳長度再傳內容,怕錯的話,大不了再加個 CRC 。


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

所有回覆

  • 1. 當"傳送端"送出 很大的資料 "接收端" 會等把資料收齊 才算  "一次" receive ==> 應該不是, 有可能會是Send一次但需要Receive好幾次

    2. 這樣會不會 造成 接收端 receive 的順序會變得不一致 ==> 就我目前觀察的樣本, 正常狀態不會有順序混亂的問題.

    3. UDP應該不會自動分次送.

    4. 你可以藉由修改下文中的程式,搭配一些封包擷取的程式, 去測試並觀察你的問題.

    http://www.dotblogs.com.tw/billchung/archive/2009/06/14/8817.aspx

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2010年9月15日 上午 03:05
    版主
  • 1. 當"傳送端"送出 很大的資料 "接收端" 會等把資料收齊 才算  "一次" receive ==> 應該不是, 有可能會是Send一次但需要Receive好幾次

    2. 這樣會不會 造成 接收端 receive 的順序會變得不一致 ==> 就我目前觀察的樣本, 正常狀態不會有順序混亂的問題.

    3. UDP應該不會自動分次送.

    4. 你可以藉由修改下文中的程式,搭配一些封包擷取的程式, 去測試並觀察你的問題.

    http://www.dotblogs.com.tw/billchung/archive/2009/06/14/8817.aspx

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    1.  例如 : 傳送一個很大的圖檔 後面接著送 一個字串

         這樣  "接收端"  會不會  圖檔的封包還沒送完  字串的封包已經送到

         發生這樣的狀況  "接收端" 要如何  組回圖檔  因為 中間 若插了一個字串封包

    2.  有沒有 可能在 multitrhead 情況下 "傳送端" 傳送資料給  "接收端"  這樣 要如合 辨別 傳送資料的完整

         我先說我的想像 若 multithread 在傳送 123456789  再傳送 abcd

         會不會在client 端收到 變成 12a345b789c

     

    2010年9月15日 上午 03:13
  •  1. 通常在設計這種程式, 我們不會完全倚賴TCP協定處理完所有的事情, 會設計自己的控制機制, 例如發送前通知 (A-->B), 與接收完畢通知 (B-->A)

     2. 這要以Connect的動作是否有區分開, 以及你在接收端是否正確的產生所對應的執行個體會決定它是否有機會亂掉.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2010年9月15日 上午 03:23
    版主
  •  1. 通常在設計這種程式, 我們不會完全倚賴TCP協定處理完所有的事情, 會設計自己的控制機制, 例如發送前通知 (A-->B), 與接收完畢通知 (B-->A)

     2. 這要以Connect的動作是否有區分開, 以及你在接收端是否正確的產生所對應的執行個體會決定它是否有機會亂掉.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    謝謝Bill 大哥的說明

    我還是  有點 模糊  是否可以 再詳加說明

    或者  有相關文章  可以參考之

    因為 我現在 擔心的是 資料傳送出去的順序 與  接收到時的完整 

    例如 : 送 123456 和 abcde   收到 1ab234d

            或者 送 1234567890   收到  一次   1234  第二次 再收到 567890

    這些情況  是否有什麼解決方法 或者 是我觀念要釐清的 ~~~

    2010年9月15日 上午 03:54
  • 假設 A 傳給 B, 一般會設計類似這樣的機制

    (1) A --啟始訊號--> B

    (2) B--確認已收到啟始訊號, 請開始傳送-->A

    (3) A--傳送真正的Data-->B

    (4) B--傳送已接收完畢訊號-->A

    (5) 繼續下一輪

    另一個關於執行個體的問題, 上文所提連結中有一段

    myTcpListener = New TcpListener(IPAddress.Any, iPort)

                Dim ClientSocket As Socket
                myTcpListener.Start()

                Do
                    ClientSocket = myTcpListener.AcceptSocket()
                    If ClientSocket.Connected = True Then
                          Dim myObj As New CSState
                        myObj.myTcpListener = myTcpListener
                        myObj.ClientSocket = ClientSocket
                        myObj.mystring = Now.ToString("yyyy/MM/dd HH:mm:ss") & "已連線"
                        DisplayMsg1(myObj)
                        Dim ReceiveThread As New Thread(AddressOf ReceiveData)
                        ReceiveThread.IsBackground = True
                        ReceiveThread.Start(myObj)
                        iCount += 1
                    End If
                Loop

    這邊之所以一定要產生一個新的CSState執行個體再拋給Receive程序的原因就在於不要讓兩個不同遠端對象指向同一個記憶體空間造成混亂.

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    • 已標示為解答 布利 2010年9月18日 上午 03:13
    2010年9月15日 上午 04:12
    版主
  • 假設 A 傳給 B, 一般會設計類似這樣的機制

    (1) A --啟始訊號--> B

    (2) B--確認已收到啟始訊號, 請開始傳送-->A

    (3) A--傳送真正的Data-->B

    (4) B--傳送已接收完畢訊號-->A

    (5) 繼續下一輪

    另一個關於執行個體的問題, 上文所提連結中有一段

    myTcpListener = New TcpListener(IPAddress.Any, iPort)

                Dim ClientSocket As Socket
                myTcpListener.Start()

                Do
                    ClientSocket = myTcpListener.AcceptSocket()
                    If ClientSocket.Connected = True Then
                          Dim myObj As New CSState
                        myObj.myTcpListener = myTcpListener
                        myObj.ClientSocket = ClientSocket
                        myObj.mystring = Now.ToString("yyyy/MM/dd HH:mm:ss") & "已連線"
                        DisplayMsg1(myObj)
                        Dim ReceiveThread As New Thread(AddressOf ReceiveData)
                        ReceiveThread.IsBackground = True
                        ReceiveThread.Start(myObj)
                        iCount += 1
                    End If
                Loop

    這邊之所以一定要產生一個新的CSState執行個體再拋給Receive程序的原因就在於不要讓兩個不同遠端對象指向同一個記憶體空間造成混亂.

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    請問一下 Bill 大哥

    1~5 的過程是否  是TCP 和 UDP 執行的過程 也就是 程式會自動做這五個動作 

    若是的話  我想請問一下  4 這個動作 在接收端是否 由 receive 這個方法 把它做調(意思 就是 不會收到下一輪的資料) 是要再下一次的receive 才會收到下一輪的資料

    2010年9月15日 上午 04:29
  • 1-5是要自己設計的機制, 用以確保資料的傳輸

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2010年9月15日 上午 06:51
    版主
  • 1-5是要自己設計的機制, 用以確保資料的傳輸

     


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    不好意思 這樣 我越來越混亂了

    因為 我看一般聊天室的sample 好像沒那麼複雜

    或者 可以請您 把1~5 大概要如何實作 給小弟一點指示

     

    2010年9月15日 上午 07:13
  • 這和程式的目的有關吧 ? 如果你的設計要確保資料的正確, 就必須自己設計一些控制.

    實做流程是

    Server B -> Start Listen

    PC A --> Connect To Server B

    PCA  --> Send 一個自訂的啟始訊號 To Server B

    Server B receive 啟始訊號, 確認封包內容無誤, Send 確認啟始給PC A

    PC A receive 確認啟始, Send 要傳送的Data to Server B

    Server B receive Data, 直到接收完畢 , Send 自訂的結束訊號給 PC A

    PC A receive 自訂結束訊號, Close Socket,


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    • 已標示為解答 布利 2010年9月18日 上午 03:13
    2010年9月15日 上午 07:33
    版主
  • 這和程式的目的有關吧 ? 如果你的設計要確保資料的正確, 就必須自己設計一些控制.

    實做流程是

    Server B -> Start Listen

    PC A --> Connect To Server B

    PCA  --> Send 一個自訂的啟始訊號 To Server B

    Server B receive 啟始訊號, 確認封包內容無誤, Send 確認啟始給PC A

    PC A receive 確認啟始, Send 要傳送的Data to Server B

    Server B receive Data, 直到接收完畢 , Send 自訂的結束訊號給 PC A

    PC A receive 自訂結束訊號, Close Socket,


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    呼  應該這樣問好了

    Receive  的規則是什麼  ?!

    我的想法  是不是 以傳送端的"資料包" 為主

                //開始接收
          Sock.BeginReceive(Data, 0, 1024, SocketFlags.None, EndRead, null);

          就是若 小於 1024 的資料會就是 send 幾次 就收幾次

          ex :   receive 會 把 1234 收完 當成一個 資料包

    但我的問題又來了 若大於 1024 那怎麼辦? 

    抱歉 我怕 我的問題滿白癡  我已經不知怎麼問了 拍謝 救命啊~~~

    2010年9月15日 上午 08:13
  • 經過  今天的 整理 我大概知道 我的問題出在哪~~

    請各位高手幫我看看 我的想法是否是對的?????????

    還有 我仍有些疑問要問

    1. 其實  傳送端 與 接收端 要我自己去定義資料的protocol 例如  前四個位元組擺長度 結尾是以 crlf 結束

        這樣 接收端 只要接收到 再 parsing 就可以了

    2. 我的問題就是  若 我傳送很多個  "電文"  會不會在 接收端被截斷的狀況   例如  xxxxxx[CRLF]xx 要等到下一次receive 才又收到 xxxx[CRLF]

        這樣 我接收端要去 split "電文" 以 [CRLF] 為主  不就  會亂掉

         以上的情形是否會發生呢  還是 在send 端 送出一串電文  client 端 就是完整的接收一串電文 不會有截斷的狀況????????

        

    2010年9月15日 下午 03:31
  • 看來你找出重點了.

    會截斷, 所以需要用迴圈或其它方式把分段收到的東西組起來.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2010年9月16日 上午 04:24
    版主
  • 看來你找出重點了.

    會截斷, 所以需要用迴圈或其它方式把分段收到的東西組起來.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    Bill大哥 

    你對於這種會被截斷  有什麼好的  演算法來克服呢

    例如 我格式是 xxxx|xxxxxxxxxxxx  CRLF

    前四個位元組是 長度  ,  CRLF 是結束字元

    我今天做了一個測試 我把 BUffer 弄很小 真的會被截斷

    但 我又不知 該如何  重組  因為  可能會讀取 到的字串是  xxx CRLF xxxx|x   這樣的字串

    你有什麼好方法解嘛?

    2010年9月16日 上午 04:30
  • 有一種方式給你參考, 你在兩次Send的間隔中使用Threading.Sleep 去讓它停頓一下

    接收端使用 Socket.Available 屬性 來判斷是否有資料在Receive Buffer中.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。
    2010年9月16日 上午 04:40
    版主
  • 有一種方式給你參考, 你在兩次Send的間隔中使用Threading.Sleep 去讓它停頓一下

    接收端使用 Socket.Available 屬性 來判斷是否有資料在Receive Buffer中.


    在現實生活中,你和誰在一起的確很重要,甚至能改變你的成長軌跡,決定你的人生成敗。 和什麼樣的人在一起,就會有什麼樣的人生。 和勤奮的人在一起,你不會懶惰; 和積極的人在一起,你不會消沈; 與智者同行,你會不同凡響; 與高人為伍,你能登上巔峰。


    請問  這種  "自定格式"  有相關的文章可以參考嘛

    我好想知道  一個 "小"的完整 solution  要如何build 出來

    因為我找了  好久  都找不到 相關的文章 ~~~

    2010年9月17日 下午 04:20
  • FAQ

    本站有相當多的討論與程式碼:

    http://www.google.com.tw/search?hl=zh-TW&source=hp&q=TcpClient%7CSocket+%E6%8E%A5%E6%94%B6+%E8%BF%B4%E5%9C%88+site%3Asocial.msdn.microsoft.com%2FForums%2Fzh-TW%2F&aq=f

    我的建議是傳 byte() ,先傳長度,傳 byte() 就可以壓縮、加密,也不受語系限制而變亂碼。

    RFC 裡面一堆通訊協定的確用換行來分隔,但是我覺得這樣滿爛的,還不如先傳長度再傳內容,怕錯的話,大不了再加個 CRC 。


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