VB.net闪存XMLSocket替换应用程序

问题描述:

我想要一个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

只要这两个应用说话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