VB.NET Flash XMLSocket Substation App
質問
ソケットサーバーに接続するためにVB.NET(Express 2010)アプリを取得しようとしています(接続を開いたままにしてください)、これにどのように進みますか?現在、Flash XMLSocketを使用して動作します。既存のサーバーを使用して、フラッシュなしで新しいクライアントを構築しようとしています。
現在、メッセージを表示する単純なウィンドウとメッセージを送信する場所を使用しています。
それは私が接続されていると書いていますが、メッセージは表示されず、メッセージが効果がないように見えます。同じIPとポートを使用してサーバーにテルネットすると、メッセージが入ってくるのを見ることができるので、接続できることがわかりますサーバーに。これが私のコードです:
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を話している限り、1つはリスニングサーバーソケットを持ち、もう1つはそのサーバーソケットのIPとポート番号を知っており、それに接続するのをブロックしていませんが、どちらの言語であるかは関係ありません書かれています。TCP/IPのようなプロトコルを持っていることのポイントは、プラットフォーム、OS、フレームワーク、言語、またはその他の多くに効果的に独立していることです。
あなたのコードについては、いくつかのことが際立っています:
何かを送るたびにネットワークストリームに接続された新しいStreamWriterを作成しています。作家が閉鎖し、ほとんどの特徴的なものが行うことで自らを閉じて処分すると、基礎となるストリームを閉じます(TCPCLIENTのストリームの場合、接続を閉じます)。ライターを使用してデータを送信する場合は、毎回新しいものを作成するのではなく、インスタンス変数としてデータを保持し、再利用してください。
XMLSocketプロトコルについて読むことから、送信および受信した文字列をヌル終了する必要があるようです。つまり、内部のループです
BuildString
データを文字列に分割するときに10ではなく0を探す必要があり、Send
nul文字を追加する必要があります(Chr(0)
)ではなくvbCr
送信するすべての文字列に。本当にエンコードを使用してバイトをcharに変換する必要があります。既存のコード(上記のように固定されている場合)は、少なくともいくつかのデータを表示する必要があります。ただし、1 byte == 1 charという仮定のために、データが破損している可能性があります。これは、Unicodeが大きくヒットしてからめったに場合はありません。 :)ストリームから直接読むのではなく、StreamReaderを使用することをお勧めします。StreamReaderは、舞台裏(デフォルトでUTF-8がIIRC)の背後にあるエンコードを使用し、ほとんどのGoryの詳細を処理するので、 Charを取得するために読み取るバイト数を心配する必要はありません。しかし、StreamReadersには、Async Readsを実行するためのものが組み込まれていません。ストリームリーダーを使用するには、少し変更して、スレッドを生成する必要があります。
デコーダーを直接使用できます。これは、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
(ところで、コメントは面白いので、構文の強調表示が愚かではなく動作します。)