none
關於Socket 在不中斷連線下的狀況,繼續發送資料 RRS feed

  • 問題

  • 請問各位大大
    小弟有個疑惑是 當我使用下面的方式

    我一定要 CLose 資料才能送到 Server端
    如果我想要不中斷 送完 下次確認連線還存在的時候繼續送不知道能不能達到呢?


    我也有嘗試過非同步但似乎也是這樣的狀況哩

    是不是我哪邊觀念錯誤了 麻煩各位指正一下 感謝您 :D

          ''開始連線動作.
                    'Try
                    '    If .ConnectSuccess = True Then

                    '        '傳送資料   ' Send the message to the connected TcpServer. 
                    '        Stream = .TCP.GetStream
                    '        Stream.WriteTimeout = 500
                    '        SendString = System.Text.Encoding.ASCII.GetBytes(Me.xCommand)
                    '        Stream.Write(SendString, 0, SendString.Length)

                    '        '讀取資料     Receive the TcpServer.response.       
                    '        Data = New [Byte](256) {}

                    '        'Try
                    '        ' Read the first batch of the TcpServer response bytes.
                    '        Stream.ReadTimeout = 500
                    '        Dim bytes As Int32 = Stream.Read(Data, 0, Data.Length)
                    '        RecvString = ""
                    '        RecvString = System.Text.Encoding.ASCII.GetString(Data, 0, bytes)
                    '        Stream.Close()
                    '        'Stream.EndWrite(IAsyncResult)

                    '        'Catch ex As Exception

                    '        'End Try

                    '    Else
                    '        ' MsgBox("連線失敗!")
                    '    End If
                    'Catch ex As Exception
                    '    '如果發生任何錯誤就重新連線
                    '    .ConnectSuccess = False
                    'End Try

    2009年11月20日 下午 06:03

解答

  • 應該不用close吧.
    你可以看一下這篇文章, Client並沒有Close, 可以一直送
    http://www.dotblogs.com.tw/billchung/archive/2009/06/14/8817.aspx
    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    • 已標示為解答 Max197 2009年11月22日 下午 02:09
    2009年11月20日 下午 08:24
    版主
  • 你是自定通訊協定還是標準的 RFC 內的通訊協定?
    一般通訊協定命令送出有規定要換行字元,看不到你有這段。

    通訊流程:
    .Net 程式 -> 送出緩衝區 (預設 8kb) -> 系統網路送出 -> 接收緩衝區 -> 對方程式

    所以很明確的,對方接收時,不見得同時收到,特別是字串,天知道字串多長,自定通訊協定時請定義清楚。
    T.L. Cheng
    • 已標示為解答 Max197 2009年11月22日 下午 02:09
    2009年11月21日 上午 07:12
    版主

所有回覆

  • 應該不用close吧.
    你可以看一下這篇文章, Client並沒有Close, 可以一直送
    http://www.dotblogs.com.tw/billchung/archive/2009/06/14/8817.aspx
    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    • 已標示為解答 Max197 2009年11月22日 下午 02:09
    2009年11月20日 下午 08:24
    版主

  • 那就怪了, 嗯嗯 我試試看大大地寫法

    感謝您 :D
    2009年11月21日 上午 02:52
  • 你是自定通訊協定還是標準的 RFC 內的通訊協定?
    一般通訊協定命令送出有規定要換行字元,看不到你有這段。

    通訊流程:
    .Net 程式 -> 送出緩衝區 (預設 8kb) -> 系統網路送出 -> 接收緩衝區 -> 對方程式

    所以很明確的,對方接收時,不見得同時收到,特別是字串,天知道字串多長,自定通訊協定時請定義清楚。
    T.L. Cheng
    • 已標示為解答 Max197 2009年11月22日 下午 02:09
    2009年11月21日 上午 07:12
    版主
  • 嗯嗯嗯

    真的可以

    原來是我接收端那邊寫錯了 ^^

                       ' Enter the listening loop.
                        If TL.Pending = True Then
                            'Console.Write("Waiting for a connection... ")

                            ' Perform a blocking call to accept requests.
                            ' You could also user server.AcceptSocket() here.
                            Dim client As TcpClient = TL.AcceptTcpClient()
                            'Console.WriteLine("Connected!")

                            data = Nothing
                            ' Get a stream object for reading and writing
                            Dim stream As NetworkStream = client.GetStream()
                            Dim i As Int32

                            Try
                                ' Loop to receive all the data sent by the client.
                                i = stream.Read(bytes, 0, bytes.Length)
                                While (i <> 0)
                                    ' Translate data bytes to a ASCII string.
                                    data = data & System.Text.Encoding.ASCII.GetString(bytes, 0, i)

                                    ' Process the data sent by the client.
                                    data = data.ToUpper()
                                    Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)

                                    ' Send back a response.
                                    stream.Write(msg, 0, msg.Length)
                                    Console.WriteLine("Sent: {0}", data)

                                    

                                    Try
                                        'i = stream.Read(bytes, 0, bytes.Length)   <<<<<<<<<<<<<<<<<<<<<<< 程式跑道這邊就會出現System.IO  錯誤 
                                        但他也沒有跑到底下  Dim LLK As String = "" 那邊  就死在這邊了
                                        所以我把這段註解掉 加上這個 Exit While 就可以囉   只是這樣好像就不曉得對方到底真實是傳了多少東西過了 只能接收一次 1024 byte 的資料了
                                     Catch ex As Exception
                                        Dim LLK As String = ""
                                    End Try
                                   

                                End While
                            Catch ex As Exception
                                Dim P As String = ""
                            End Try
    2009年11月22日 下午 02:09
  • ?
    你用 Try 還會跑出錯誤?

    你迴圈寫的很怪,既有討論可以先看看:
    http://social.msdn.microsoft.com/Search/zh-TW/?Refinement=112&query=TcpClient%20Available
    論壇是網友平等互助 保證解答請至 微軟技術支援服務
    提問時,錯誤情境描述與錯誤訊息很重要,情境描述包含你做了什麼,預期的結果與實際發生的結果。一個最爛的問法範例:「我的電腦電腦怎麼不能開機?」誰知道你家是不是沒電還是你根本找不到電源鈕。
    2009年11月22日 下午 02:13
  • 小弟有使用  Thread 呼叫這個 函數

    只是 呵 他真的跑道那邊 不會進到  Try 我也不曉得耶

    我還特別用
     Dim LLK As String = ""

    來當中斷點....  也抓不到說

            Public Sub a_Run(ByVal n As Object)
                ' Buffer for reading data
                Dim bytes(1024) As Byte
                Dim data As String = Nothing


                Do

                    Application.DoEvents()

                    System.Threading.Thread.Sleep(500)

                    Try
                        TL.Start()
                    Catch ex As Exception
                        Try
                            TL.Stop()
                            Q.Items(xIdx).SubItems(4).Text = "ERRORERRORERROR"
                        Catch ex2 As Exception

                        End Try
                    End Try
                    Try

                        ' Enter the listening loop.
                        If TL.Pending = True Then
                            'Console.Write("Waiting for a connection... ")

                            ' Perform a blocking call to accept requests.
                            ' You could also user server.AcceptSocket() here.
                            Dim client As TcpClient = TL.AcceptTcpClient()
                            'Console.WriteLine("Connected!")

                            data = Nothing
                            ' Get a stream object for reading and writing
                            Dim stream As NetworkStream = client.GetStream()
                            Dim i As Int32

                            Try
                                ' Loop to receive all the data sent by the client.
                                i = stream.Read(bytes, 0, bytes.Length)
                                While (i <> 0)
                                    ' Translate data bytes to a ASCII string.
                                    data = data & System.Text.Encoding.ASCII.GetString(bytes, 0, i)

                                    ' Process the data sent by the client.
                                    data = data.ToUpper()
                                    Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)

                                    ' Send back a response.
                                    stream.Write(msg, 0, msg.Length)
                                    Console.WriteLine("Sent: {0}", data)

                                    Try
                                        'i = stream.Read(bytes, 0, bytes.Length)
                                    Catch ex As Exception
                                        Dim LLK As String = ""
                                    End Try
                                    Exit While

                                End While
                            Catch ex As Exception
                                Dim P As String = ""
                            End Try
                            M = data
                            client.Close()
                            client = Nothing
                        End If

                    Catch ex As Exception
                        Dim P As String = ""
                    End Try

                Loop

            End Sub

        End Class

    2009年11月22日 下午 02:16
  • 這邊有一篇 TcpClient 讀資料的討論,我覺得你先看一下,把你整個讀資料的迴圈調整過:
    http://social.msdn.microsoft.com/forums/zh-TW/232/thread/bd9760c0-23e3-41a5-bc15-0b26b67701db/

    你在迴圈內有兩段不限長度的讀法,實在很怪:
    Try

                                      i = stream.Read(bytes, 0, bytes.Length)

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

    Bill ChungMVP
    大大提供的資料已經可以了
    但其實我還是納悶 其實我的作法是 國外網站 copy下來滴
    為什麼 , 一個可以這樣用一個不行呢?
    至於您提及的
               Try
                                        'i = stream.Read(bytes, 0, bytes.Length)<<<<<<<<<<<<<<<<<<<<<<<<<<<
                                    Catch ex As Exception
                                        Dim LLK As String = ""
                                    End Try
                                    Exit While


    我那時候也在想,後來我覺得他應該是透過 
      While (i <> 0)
        i = stream.Read(bytes, 0, bytes.Length)<<<<<<<<<<<<<<<<<<<<<<<<<<<
     end While 

    想要不斷地把資料由Buffer 抓下來 直到為空

    但實際上在用的時候,如果有資料應該是不會出錯
    但沒資料他會出錯 且Try抓不到他的錯誤就會在那邊出現死迴圈了

    不過至少問題解決囉 ^^
    2009年11月23日 上午 03:59
  • 在MSDN的文件中是使用 [NetworkStream.DataAvailable 屬性 ] 來做為迴圈條件的
    以下程式碼引述自MSDN文件庫 NetworkStream. DataAvailable 屬性 的範例

    If myNetworkStream.CanRead Then
       Dim myReadBuffer(1024) As Byte
           Dim myCompleteMessage As StringBuilder = New StringBuilder()
       Dim numberOfBytesRead As Integer = 0

       ' Incoming message may be larger than the buffer size.
       Do
          numberOfBytesRead = myNetworkStream.Read(myReadBuffer, 0, myReadBuffer.Length)
               myCompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(myReadBuffer, 0, numberOfBytesRead))
       Loop While myNetworkStream.DataAvailable

       ' Print out the received message to the console.
           Console.WriteLine(("You received the following message : " + myCompleteMessage.ToString()))
    Else
       Console.WriteLine("Sorry.  You cannot read from this NetworkStream.")
    End If

    學而不思則罔, 思而不學則殆.
    如果你一直都看不懂、不想學習看懂、抗拒看懂MSDN Library的話,那你最好放棄想要寫好程式這件事
    如果你自私地不肯回饋與分享,那別人為何要花時間回答你的問題?
    2009年11月23日 上午 04:24
    版主
  • 嗯嗯嗯 我瞭解您的意思了 我原本有使用這個方法來測試這個問題 感謝您 與其他大大地協助 :D '以下為非同步方法================================================================== 'Private Sub EndWriteCallback(ByVal ar As IAsyncResult) ' Dim state As StateObject = DirectCast(ar.AsyncState, StateObject) ' Dim client As TcpClient = state.Client ' Try ' Dim stream As NetworkStream = client.GetStream() ' stream.EndWrite(ar) ' state.Data.Length = 0 ' If stream.CanRead Then ' stream.BeginRead(state.Buffer, 0, state.BufferSize, AddressOf EndReadCallback, state) ' End If ' Catch ex As Exception ' client.Close() ' 'DisplayStatus(String.Format("Ready (last error: {0})", ex.Message)) ' End Try ' SendStatus = True 'End Sub 'Private Sub EndConnectCallback(ByVal ar As IAsyncResult) ' Dim state As StateObject = DirectCast(ar.AsyncState, StateObject) ' Dim client As TcpClient = state.Client ' Try ' client.EndConnect(ar) ' If client.Connected Then ' Dim stream As NetworkStream = client.GetStream() ' If stream.CanWrite Then ' Dim send As Byte() = Encoding.UTF8.GetBytes(state.Data.ToString()) ' stream.BeginWrite(send, 0, send.Length, AddressOf EndWriteCallback, state) ' End If ' Else ' 'DisplayStatus(String.Format("Ready (last error: {0})", "Connect Failed!")) ' End If ' Catch ex As Exception ' client.Close() ' 'DisplayStatus(String.Format("Ready (last error: {0})", ex.Message)) ' End Try 'End Sub 'Private Sub EndReadCallback(ByVal ar As IAsyncResult) ' Dim state As StateObject = DirectCast(ar.AsyncState, StateObject) ' Dim client As TcpClient = state.Client ' Dim stream As NetworkStream = client.GetStream() ' Dim bytesRead As Integer = stream.EndRead(ar) ' If bytesRead > 0 Then ' state.Data.Append(Encoding.UTF8.GetString(state.Buffer, 0, bytesRead)) ' stream.BeginRead(state.Buffer, 0, state.BufferSize, AddressOf EndReadCallback, state) ' Else ' client.Close() ' DisplayResults(state.Data.ToString()) ' End If 'End Sub 'Public Sub DisplayResults(ByVal text As String) ' ' If InvokeRequired Then ' 'BeginInvoke(New Action(DisplayResults), text) ' ' End If 'End Sub '以上為非同步方法==================================================================
    2009年11月23日 上午 04:51