2010-08-20 66 views
0

我想要一個VB.net(快遞2010)應用程序連接到套接字服務器(保持連接打開),我會怎麼做呢?現在它使用Flash XMLsocket,我試圖用現有的服務器構建一個沒有Flash的新客戶端。VB.net閃存XMLSocket替換應用程序

目前我只是使用一個簡單的窗口顯示消息,以及一個地方發送消息。

它說我已連接,但它不顯示消息,並且當我使用相同的IP和端口telnet到服務器時,發送的消息看起來沒有任何作用,所以我可以看到消息進入我的系統知道我可以連接到服務器。這裏是我的代碼:

Imports System.Text 
Imports System.Net.Sockets 


Public Class Form1 
    Inherits System.Windows.Forms.Form 

    Public Delegate Sub DisplayInvoker(ByVal t As String) 

    Private mobjClient As TcpClient 
    Private marData(1024) As Byte 
    Private mobjText As New StringBuilder() 

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load 
     mobjClient = New TcpClient("example.com", 7777) 
     DisplayText("Connected to host " & "example.com") 

     mobjClient.GetStream.BeginRead(marData, 0, 1024, AddressOf DoRead, Nothing) 
    End Sub 

    Private Sub btnSend_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnSend.Click 
     Send(txtSend.Text) 
     txtSend.Text = "" 
    End Sub 

    Private Sub Send(ByVal t As String) 
     Dim w As New IO.StreamWriter(mobjClient.GetStream) 
     w.Write(t & vbCr) 
     w.Flush() 
     DisplayText(vbNewLine & "Sent " & t) 
    End Sub 

    Private Sub DoRead(ByVal ar As IAsyncResult) 
     Dim intCount As Integer 
     Try 
      intCount = mobjClient.GetStream.EndRead(ar) 
      If intCount < 1 Then 
       MarkAsDisconnected() 
       Exit Sub 
      End If 

      BuildString(marData, 0, intCount) 

      mobjClient.GetStream.BeginRead(marData, 0, 1024, AddressOf DoRead, Nothing) 
     Catch e As Exception 
      MarkAsDisconnected() 
     End Try 
    End Sub 

    Private Sub BuildString(ByVal Bytes() As Byte, ByVal offset As Integer, ByVal count As Integer) 
     Dim intIndex As Integer 

     For intIndex = offset To offset + count - 1 
      If Bytes(intIndex) = 10 Then 
       mobjText.Append(vbLf) 

       Dim params() As Object = {mobjText.ToString} 
       Me.Invoke(New DisplayInvoker(AddressOf Me.DisplayText), params) 

       mobjText = New StringBuilder() 
      Else 
       mobjText.Append(ChrW(Bytes(intIndex))) 
      End If 
     Next 
    End Sub 

    Private Sub MarkAsDisconnected() 
     txtSend.ReadOnly = True 
     btnSend.Enabled = False 
     DisplayText(vbNewLine & "Dissconnected") 
    End Sub 

    Private Sub DisplayText(ByVal t As String) 
     txtDisplay.AppendText(t) 
    End Sub 
End Class 
+0

雞蛋裏挑骨頭:客戶通常連接到服務器,而不是周圍的其他方式。 FTP例外的一些協議允許服務器打開輔助套接字進行數據傳輸。 – cHao 2010-08-20 02:57:52

+0

XmlSocket部分似乎特別相關,因爲它定義了使用的協議,但遠程服務器的語言/平臺無關緊要。不過,它確實增加了一些重要的理由,那就是你應該使用像UTF-8這樣的編碼來解碼字符串,而不是假設每個字節都是一個字符(這種情況很少出現)。 – cHao 2010-08-20 15:13:19

回答

1

只要這兩個應用說話TCP/IP,一個具有聽服務器套接字,其他人都知道服務器套接字的IP和端口號,而不是從連接到受阻它與任何應用程序的編寫語言無關。擁有像TCP/IP這樣的協議的關鍵在於它實際上獨立於平臺,操作系統,框架,語言或其他任何東西。

至於你的代碼,幾件事情中脫穎而出:

  • 你正在創建連接到每次發送的任何時候網絡流的新的StreamWriter。如果編寫器在大多數IDisposables所做的最終化過程中關閉並自行部署,它將關閉底層流(對於TcpClient的流,將關閉連接)。如果您要使用編寫器發送數據,請將其中一個作爲實例變量並重復使用,而不是每次都創建一個新實例。

  • 從閱讀有關XmlSocket協議,似乎發送和接收的字符串應以空終止。也就是說,BuildString內的循環在將數據分解爲字符串時應該查找0而不是10,而Send應該爲它發送的每個字符串附加一個空字符(Chr(0))而不是vbCr

  • 你真的應該使用編碼將字節轉換爲字符。假設有任何要發送的數據,你現有的代碼(如上所述)至少應該顯示一些數據。不過,你可能會發現數據被破壞了,因爲假設1字節== 1字符 - 自從Unicode把它打得很大以後很少出現這種情況。 :)我建議你使用StreamReader而不是直接從流中讀取 - StreamReader在幕後使用編碼(默認爲UTF-8,IIRC),並且會處理大部分的血腥細節,所以你不需要擔心需要讀取多少個字節才能獲得字符。但StreamReaders沒有內置的東西來執行異步讀取。你必須改變你的東西,併爲它產生一個線程,以便使用StreamReader。

您可以直接使用解碼器,這幾乎是StreamReader的功能。使用它是這樣的:

''// This is important! Keep the Decoder and reuse it when you read this socket. 
''// If you don't, a char split across two reads will break. 
Private _decoder As Decoder = UTF8Encoding.GetDecoder() 


Private Sub BuildString(bytes() As Byte, offset As Integer, byteCount As Integer) 

    ''// Here's where the magic happens. The decoder converts bytes into chars. 
    ''// But it remembers the final byte(s), and doesn't convert them, 
    ''// until they form a complete char. 
    Dim chars(bytes.Length) As Char 
    Dim charCount as Integer = _decoder.GetChars(bytes, offset, byteCount, chars, 0) 

    For i as Integer = 0 to charCount - 1 
     if chars(i) = chr(0) then   ''// The fix for bullet #2 
      mObjText.Append(vbLf) 

      Dim params() As Object = {mobjText.ToString} 
      Me.Invoke(New DisplayInvoker(AddressOf Me.DisplayText), params) 

      ''// You don't have to make a new StringBuilder, BTW -- just clear it. 
      mObjText.Length = 0 
     else 
      mObjText.Append(chars(i)) 
     end if 
    Next 
End Sub 

(順便說一句,讓語法高亮的行爲多少有點愚蠢的評論都開始笑。)

+0

是的,我明白那個部分,我需要的是visual basic.net可以做到這一點(客戶端,而不是服務器),我可以自己解析它,一旦我可以獲得數據。 – 2010-08-20 12:35:18

+0

@ Bubby4j:更新(如果SO沒有告訴你)。 – cHao 2010-08-21 13:29:52

+0

它的工作原理!非常感謝!只要知道它的作用,我會盡快接受這個答案。 – 2010-08-22 03:12:17