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
只要这两个应用说话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
(顺便说一句,让语法高亮的行为多少有点愚蠢的评论都开始笑。)
是的,我明白那个部分,我需要的是visual basic.net可以做到这一点(客户端,而不是服务器),我可以自己解析它,一旦我可以获得数据。 – 2010-08-20 12:35:18
@ Bubby4j:更新(如果SO没有告诉你)。 – cHao 2010-08-21 13:29:52
它的工作原理!非常感谢!只要知道它的作用,我会尽快接受这个答案。 – 2010-08-22 03:12:17
鸡蛋里挑骨头:客户通常连接到服务器,而不是周围的其他方式。 FTP例外的一些协议允许服务器打开辅助套接字进行数据传输。 – cHao 2010-08-20 02:57:52
XmlSocket部分似乎特别相关,因为它定义了使用的协议,但远程服务器的语言/平台无关紧要。不过,它确实增加了一些重要的理由,那就是你应该使用像UTF-8这样的编码来解码字符串,而不是假设每个字节都是一个字符(这种情况很少出现)。 – cHao 2010-08-20 15:13:19