Вопрос

Я пытаюсь получить приложение VB.Net (Express 2010) для подключения к серверу сокета (сохраняя открытое соединение), как бы я поступил в это? Прямо сейчас он работает с помощью Flash XMLSocket, я пытаюсь построить новый клиент без Flash, используя существующий сервер.

В настоящее время я просто использую простое окно, отображающее сообщения, а также место для отправки сообщений.

Он говорит, что я подключен, но не отображается никаких сообщений, и отправленные сообщения не имеют никакого эффекта, когда я телнет на сервер, используя тот же 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, у одного есть сокет сервера прослушивания, а другой знает номер IP и порта этого сокета сервера и не блокируется от подключения к нему, не имеет значения, на каком языке либо приложение написано. Точка имела протокол, такой как TCP / IP, заключается в том, что он эффективно не зависит от платформы, ОС, рамки, языка или многое другое.

Что касается вашего кода, выделяются несколько вещей:

  • Вы создаете новый Streamwriter, прикрепленный к сетевому потоку каждый раз, когда вы отправляете что-либо. Если писатель закрывается и утилизируется на завершение, что большинство IDSPLABLES делают, он закроет основной поток (который, в случае потока TCPClient, закроет соединение). Если вы собираетесь использовать писатель для отправки данных, сохраняйте один в качестве переменной экземпляра и повторно используйте его, а не создавать новый каждый раз.

  • От чтения про протокола XMLSocket, кажется, что строки, отправленные и полученные должны быть расторгнутыми в нуле. То есть ваша петля внутри BuildString следует искать 0, а не 10 при расстановке данных на строки, а также Send должно быть добавление персонажа Nul (Chr(0)), а не чем vbCr к каждой строке, которую он отправляет.

  • Вы действительно должны использовать кодировку для преобразования байтов для Chars. Ваш существующий код (при исправлении, как указано выше), должен, по крайней мере, покажет вам некоторые данные, предполагая, что есть какие-либо отправляемые. Вы вполне можете найти поврежденные данные, однако из-за предположения, что 1 байт == 1 CHAR - что редко бывает случай, поскольку Unicode ударил его большим. :) Я бы предложил, чтобы вы использовали StreameReader, а не чтение непосредственно из потока - Streamreader использует кодировку за кулисами (UTF-8 по умолчанию, IIRC), и будет справиться с большинством деталей горы, так что вы Не нужно беспокоиться о том, сколько байтов читать, чтобы получить чар. Но упрочны не имеют встроенных в них вещей, чтобы сделать async читать. Вам нужно немного менять свои вещи и порождать нить для него, чтобы использовать 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

(Кстати, комментарии начинаются смешно, так что подсветка синтаксиса действует менее глупым.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top