Problem beim empfangen von "Zeilen" -> Daten kommen "zerhackt" an =(

  • VB.NET

Es gibt 8 Antworten in diesem Thema. Der letzte Beitrag () ist von MrTweek.

    Problem beim empfangen von "Zeilen" -> Daten kommen "zerhackt" an =(

    Hallo,
    ich schreibe zurzeit einen Gameserver, jener so verlangt es das Spiel, muss daten in form eines IRC-Chats senden, (IRC-Befehle)
    das problem was ich habe, dass ich daten empfange, jedoch bei langen "Zeilen", die das Spiel sendet, diese zerhackt ankommen <.<

    hier mal ein Beispiel:

    die zeile muss lauten:

    Quellcode

    1. vercheck xxxxx xxxxxx
    2. vercheck 4608 32512
    3. lobcount 4608
    4. whereto Tibsun Tibpass99 4608 32512 Íkey%
    5. quit


    die rotmakierte zeile, wird "zerhackt" gesendet (welche aber eine ganze zeile sein muss!, das spiel sendet sie auch als ganze!)... aber ich finde den fehler nicht :/

    ich erhalte aber:

    Quellcode

    1. vercheck xxxxx xxxxxx
    2. vercheck 4608 32512
    3. lobcount 4608
    4. whereto T
    und

    Quellcode

    1. ibsun Tibpass99 4608 32512 Íkey%



    hier ist die funktion:



    VB.NET-Quellcode

    1. Private Sub _reading(ByVal ar As IAsyncResult)
    2. Dim asyncState = DirectCast(ar.AsyncState, ReadAsyncState)
    3. Dim buffer = asyncState.Buffer
    4. Dim gc = asyncState.gc
    5. If gc.client IsNot Nothing And gc.client.Connected And gc.stream IsNot Nothing And gc.stream.CanRead Then
    6. Dim bytecount As Integer = gc.stream.EndRead(ar)
    7. If bytecount > 0 Then
    8. buffer(_endpoint.Server.ReceiveBufferSize - 1) = Convert.ToByte(0)
    9. Dim _rline As String = Encoding.ASCII.GetString(buffer, 0, buffer.Length)
    10. While gc.stream.DataAvailable And gc.stream.CanRead
    11. bytecount = gc.stream.Read(buffer, 0, gc.client.ReceiveBufferSize)
    12. _rline = Encoding.ASCII.GetString(buffer, 0, buffer.Length)
    13. End While
    14. If _rline.Length > 0 Then
    15. Dim Msg As String = _rline.ToString
    16. Dim message() As String = Msg.Split(" ")
    17. MsgBox(Msg)
    18. If Msg.StartsWith("verchk") Then handle_verchk_command(gc, Message)
    19. If Msg.StartsWith("lobcount") Then handle_lobcount_command(gc, Message)
    20. If Msg.StartsWith("whereto") Then handle_whereto_command(gc, Message)
    21. If Msg.StartsWith("quit") Then handle_quit_command(gc, Message)
    22. End If
    23. buffer(_endpoint.Server.ReceiveBufferSize - 1) = Convert.ToByte(0)
    24. If gc.stream.CanRead Then
    25. gc.stream.BeginRead(buffer, 0, _endpoint.Server.ReceiveBufferSize, AddressOf _reading, New ReadAsyncState With {.Buffer = buffer, .gc = gc})
    26. End If
    27. Else
    28. Gameclients.Remove(gc)
    29. Exit Sub
    30. End If
    31. End If
    32. End Sub
    Der Client wird halt die Daten in 2 Schritten senden. Der Client muss dem Server schon mitteilen, wieviele Bytes da kommen oder alternativ ein "Steuerzeichen" senden, dass dem Server sagt, hier ist die Übertragung erst mal zu Ende. Send- bzw. ReceiveBufferSize hat damit nichts zu tun. Also, sende dem Server erst einen Integer/Long, der angibt, wieviele Bytes zu lesen sind, richte die Grösse des Buffers darauf ein oder lies die Bytes in eine Liste. Sind die zu erwartenden Bytes gelesen, fahre fort.

    Ach ja, OPTION STRICT ON!
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    sende dem Server erst einen Integer/Long, der angibt, wieviele Bytes zu
    lesen sind, richte die Grösse des Buffers darauf ein oder lies die Bytes
    in eine Liste. Sind die zu erwartenden Bytes gelesen, fahre fort.
    Ist leider nicht möglich, da das Spiel nicht von mir entwickelt wurde, sondern von Westwood, lese ich die daten, mittels "Streamreader.readline", dann bekommt er auch die lineendings,
    gibt es eine möglichkeit den streamreader dafür asyncron zu nutzen? (dieser macht nicht diese Zeilen-Fehler =( )
    Die Steuerzeichen werden doch übertragen, also kannst Du doch bis zu diesem Punkt lesen. Gibt es keine Definition des Protokolls?
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    das ist normales IRC-verhalten nach RFC X(

    "WOL ServServ is WOLv2 service only. It using standart IRC protocol
    concept of commands and server replyes but is not used for any
    chat/games functions.
    This server uses hostname servserv.westwood.com
    and port 4005. This is hardcoded on client side. Server is used for
    Gateway stuff - all WOLv2 clients firstly connect to this server and get
    list of possible WOL IRC servers. They are divided geographically over
    the world ie. US West, Europe, Asia.
    "

    es gibt eine Version in java X( .... aber der macht das so =(:

    Quellcode

    1. try
    2. {
    3. message = new String(buf, offset, i - offset - (i > 0 && buf[i-1] == '\r' ? 1 : 0), encoding);
    4. System.out.println("Readed: " +message);
    5. }
    6. catch (Exception e)
    7. {
    8. System.out.println("Unexpected exception when converting bytes to string");
    9. }

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MrTweek“ ()

    Nun, lege Deinen Buffer groß genug fest. Treffen Daten ein, so musst Du prüfen, ob die letzten 2 Byte in Deinem Buffer vbCrLf entsprechen. Das ist, wie ich es verstehe, das Signal, dass die Übertragung abgeschlossen ist. Trifft dies nicht zu, so übergib den Buffer an eine temporäre Liste und lies erneut Daten vom Socket. Das wiederholst Du solange, bis das Ende der Übertragung erkannt wurde. Dann erzeugst Du aus dem temporären Buffer den String und wertest entsprechend aus.

    Ich hab mir das Protokoll kurz angesehen, bin aber zu faul und zu müde, mich jetzt tiefer damit auseinander zu setzen. Ein Test hat jedoch funktioniert. Es ist auch egal, wie dieses Signal aussieht, das Prinzip ist immer das selbe. Lies solange Daten, bis das entsprechende Signal eintrifft.
    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    und wie kann ich das steuerzeichen ermitteln? :( Kannst Du mir da mal ein Schnipsel Code zeigen, wie man das "auswertet"? ...

    Das "Auswerten, werde ich dann wohl in einer "globalen klasse" machen müssen, da ich ja später 4 Listener brauche, die diese Methode anwenden müssen.
    Hier ein ganz rudimentäres Beispiel. Es fehlt jede Fehlerbehandlung, jede Struktur, soll Dir nur das Prinzip aufzeigen.

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System.Net
    2. Imports System.Net.Sockets
    3. Imports System.Text
    4. Public Class Form1
    5. Private _client As Socket = Nothing
    6. Private _serverIP As IPAddress = IPAddress.Parse("46.105.123.98")
    7. Private _serverPort As Integer = 4005
    8. Private _buffer(4095) As Byte
    9. Private _tmpBuffer As New List(Of Byte)
    10. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    11. If _client Is Nothing Then
    12. _client = New Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp)
    13. _client.Connect(New IPEndPoint(_serverIP, _serverPort))
    14. If _client.Connected Then
    15. Dim message() As Byte = Encoding.ASCII.GetBytes("WHERETO" & vbCrLf)
    16. ClientReceive()
    17. _client.Send(message, SocketFlags.None)
    18. End If
    19. End If
    20. End Sub
    21. Private Sub ClientReceive()
    22. _client.BeginReceive(_buffer, 0, _buffer.Length, SocketFlags.None, AddressOf ClientEndReceive, Nothing)
    23. End Sub
    24. Private Sub ClientEndReceive(ar As IAsyncResult)
    25. Dim recLen As Integer = _client.EndReceive(ar)
    26. If recLen = 0 Then
    27. _client.Close()
    28. Exit Sub
    29. End If
    30. If _buffer(recLen - 2) = 13 AndAlso _buffer(recLen - 1) = 10 Then
    31. If Not _tmpBuffer.Count = 0 Then
    32. _tmpBuffer.AddRange(_buffer.ToList().GetRange(0, recLen))
    33. Dim message As String = Encoding.ASCII.GetString(_tmpBuffer.ToArray())
    34. Me.Invoke(Sub()
    35. TextBox1.AppendText(message)
    36. End Sub)
    37. _tmpBuffer.Clear()
    38. Else
    39. Dim message As String = Encoding.ASCII.GetString(_buffer, 0, recLen)
    40. Me.Invoke(Sub()
    41. TextBox1.AppendText(message)
    42. End Sub)
    43. End If
    44. Else
    45. _tmpBuffer.AddRange(_buffer.ToList().GetRange(0, recLen))
    46. End If
    47. ClientReceive()
    48. End Sub
    49. End Class

    Die Unendlichkeit ist weit. Vor allem gegen Ende. ?(
    Manche Menschen sind gar nicht dumm. Sie haben nur Pech beim Denken. 8o
    oki habe mir mal den letzten block kopiert... und habe die funktion abgeändert...

    VB.NET-Quellcode

    1. Private Sub EndRead(ByVal ar As IAsyncResult)
    2. If MyBase.IsDisposed Then Return
    3. Dim read As Integer = _Stream.EndRead(ar)
    4. Dim message As String = ""
    5. If read = 0 Then 'leere Datenübermittlung signalisiert Verbindungsabbruch
    6. Return
    7. End If
    8. Dim SB As New StringBuilder(Encoding.UTF8.GetString(Buf, 0, read), 9999)
    9. Dim splitted_line As Integer = 0
    10. Do While _Stream.DataAvailable
    11. read = _Stream.Read(Buf, 0, Buf.Length)
    12. SB.Append(Encoding.UTF8.GetString(Buf, 0, read), Buf.Length, read)
    13. Loop
    14. If Buf(read - 2) = 13 AndAlso Buf(read - 1) = 10 Then
    15. If Not _tmpbuffer.Count = 0 Then
    16. _tmpBuffer.AddRange(Buf.ToList().GetRange(0, read))
    17. message = Encoding.ASCII.GetString(_tmpBuffer.ToArray())
    18. _tmpBuffer.Clear()
    19. Else
    20. message = Encoding.ASCII.GetString(Buf, 0, read)
    21. End If
    22. Else
    23. _tmpBuffer.AddRange(Buf.ToList().GetRange(0, read))
    24. End If
    25. MsgBox(message)
    26. _Stream.BeginRead(Buf, 0, Buf.Length, AddressOf EndRead, Nothing)
    27. End Sub


    den teil mit dem "whereto", habe ich ausgelassen, da es ja variable ist, was da ankommt... aber es funktioniert nun :)
    ich werde das ganze mal in einer klasse packen, da ich noch 4 server für das project bauen muss <.<