![]() |
TIdTCPServer Byte Packets (Indy10)
Hey Delphianer!
Ich möchte eine Server Anwendung schreiben, die mit einem Game Client kommuniziert. Das Problem ist, das ich nicht weiß wie ich ganze Packets empfange. Im moment mach ich das so:
Delphi-Quellcode:
Ich empfange also im moment einzelne Bytes was heißen soll, dass ich dann schauen muss was dieses Paket beinhalten kann und
myByte := AContext.Connection.IOHandler.ReadByte;
if (myByte = 2) then // 0x02 (Connect) begin Log.Lines.Add('Received: Packet 0x02'); // usw. end else if // usw. schließlich auswerten msus wieviel Pakete tatsächlich angekommen sind. So habe ich sehr viele If bzw. Case Abfragen. Würde das Problem gerne mit nem Array oder 'nem Record lösen, kriege das aber nicht wirklich hin. Wäre cool wenn ihr mir ein Codeschnippsel posten könntet, am besten vllt noch mit folgenden Daten (damit ich die anderen 66 Packets auswerten kann :-D):
Code:
und zurückschicken müsste ich:
Packet ID ++++++ Field Name +++++++ Field Type +++++++ Example +++++++ Notes
0x01 . . . . . . Protocol Version . int . . . . . . .. 19 . . . . . .. The latest version of the protocol is 19 0x01 . . . . . . Username . . . . . string16 . . . . . TkTech . . . .. The name of the user attempting to login, max length of 16 0x01 . . . . . . Not used . . . . . long . . . . . . . 0 . . . . . .. 0x01 . . . . . . Not used . . . . . int . . . . . . .. 0 . . . . . .. 0x01 . . . . . . Not used . . . . . byte . . . . . . . 0 . . . . . .. 0x01 . . . . . . Not used . . . . . byte . . . . . . . 0 . . . . . .. 0x01 . . . . . . Not used . . . . . unsigned byte. . . 0 . . . . . .. 0x01 . . . . . . Not used . . . . . unsigned byte. . . 0 . . . . . .. -------------------------------------------------------------------------------------------------------------------------- Total Size: 23 bytes + length of strings
Code:
wäre total super wenn ihr mir helfen könntet ... ein winziges beispiel genügt, es müssen nicht alle Daten benutzt werden
Packet ID ++++++ Field Name +++++++ Field Type +++++++ Example +++++++ Notes
0x01 . . . . . . Entity ID . . . . . int . . . . . . .. 1298 . . . . . .. The Players Entity ID 0x01 . . . . . . Not used . . . . . string16 . . . . . (empty string). .. Not used 0x01 . . . . . . Map Seed . . . . . long . . . . . . . 971768181197178410 The server's map seed. Must be sent in respawn packets by the client. 0x01 . . . . . . Server mode . . . . . int . . . . . . .. 0 . . . . . .. . 0 for survival, 1 for creative 0x01 . . . . . . Dimension . . . . . byte . . . . . . . . 0 . . . . . .. . Used for specifying the players dimension -1 for hell, 0 otherwise 0x01 . . . . . . Difficulty . . . . . byte . . . . . . . 1 . . . . . .. . .0 thru 3 for Peaceful, Easy, Normal, Hard 0x01 . . . . . . World height . . . unsigned byte. . . 128 . . . . . .. . .Defaults to 128 0x01 . . . . . . Max players . . . .unsigned byte. . . 8 . . . . . .. . . .Used by the client to draw the player list -------------------------------------------------------------------------------------------------------------------------- Total Size: 23 bytes + length of strings Mfg DArc |
AW: TIdTCPServer Byte Packets (Indy10)
Zitat:
Code:
Done!
type
TMyPacket = packed record int0: integer; str16: array[0..15] of char; long0: Longint; int1: integer; nbyte0: byte; nbyte1: byte; nbyte2: byte; nbyte3: byte; end; |
AW: TIdTCPServer Byte Packets (Indy10)
Sicherheitshalber besser so:
Delphi-Quellcode:
Sonst kann es nach einem Delphi-Upgrade zu Problemen kommen.
str16: array[0..15] of AnsiChar;
|
AW: TIdTCPServer Byte Packets (Indy10)
ich habe jetzt aber ein problem mit dem auslesen des packets ...
Delphi-Quellcode:
nehmen wir mal ein ganz leichtes beispiel, also das mit dem kleinsten packet:
procedure TForm1.ServerExecute(AContext: TIdContext);
type TMyPacket = packed record id: Byte; length: Byte; username: array[0..15] of AnsiChar; { int0: integer; long0: Longint; int1: integer; nbyte0: byte; nbyte1: byte; nbyte2: byte; nbyte3: byte; } end; var ByteBuffer: TIdBytes; begin AContext.Connection.IOHandler.ReadBytes(ByteBuffer, SizeOf(tmypacket)); BytesToRaw(ByteBuffer, mypacket, SizeOf(tmypacket)); end; ich empfange: id (byte), length of username (byte), username (string) sample: id=0x02(login packet), length of username=1, weil username=77(Zeichen "M" als ASCII-Code) ich gebe das ganze mit folgendem code aus:
Delphi-Quellcode:
aus dem beispielcode resultiert folgendes:
Log.Lines.Add(IntToStr(mypacket.id));
Log.Lines.Add(IntToStr(mypacket.length));
Code:
heißt: ich konnte zwar die bytes auslesen, jedoch landen die alle im mypacket.id und für length ist nix mehr übrig, geschweige denn für username
2
0 1 0 77 0 achja ehe ich es vergesse: ich empfange überhaupt nichts, solange ich in dieser zeile SizeOf(TMyPacket) stehen habe ...
Delphi-Quellcode:
bei mir steht ne zahl drin (irrelevant welche, hauptsache: zahl<=byte, im prinzip logisch da ich immer nur ein byte empfange), kurz:
// ...
AContext.Connection.IOHandler.ReadBytes(ByteBuffer, SizeOf(tmypacket)); // ...
Delphi-Quellcode:
meine fragen noch kurz zusammengefasst:
// ...
AContext.Connection.IOHandler.ReadBytes(ByteBuffer, SizeOf(byte)); // ... warum kann ich mein Record nicht vollständig füllen? warum empfange ich keine werte bei SizeOf(TMyPacket)? Mfg DArc |
AW: TIdTCPServer Byte Packets (Indy10)
niemand ne idee?
|
AW: TIdTCPServer Byte Packets (Indy10)
Was mich ein wenig stutzig macht, ist diese Zeile
Zitat:
Weiterhin solltest Du dir die Deklaration genauer anschauen, ich seh da nämlich nichts von 'Byte' bei der 'ID'... |
AW: TIdTCPServer Byte Packets (Indy10)
danke erst mal für die antwort, schön zu sehen, dass es leute gibt die früh morgens antworten :D
nehmen wir das beispiel, welches ich im letzten post behandelt habe: ![]() Weiter oben steht die Definition der "Packets"
Code:
Die Länge des Packets, welches geschickt wird:
All packets begin with a single "Packet ID" byte. Listed packet size includes this byte. Packets are either "server to client", "client to server", or both. If not specified, assume that the packet can be sent both ways. There is no "length" field; for variable length packets, you must parse to the end to determine the length.
Code:
soll (glaube ich mal) heißen, dass ich min. 3 bytes zugeschickt bekomme (spekuliere auf benutzername min. 1 zeichen):
Total Size: 3 bytes + length of strings
1. byte: packet id 2. byte: länge der zeichenkette (länge des benutzernamens) 3. byte: das zeichen selbst habe ich zB den Namen DArc, empfange ich folgendes (3 Bytes + 3 weitere): 1. byte: packet id = 0x02 => 2 2. byte: länge meines namens = 4 3. byte: das zeichen "D" im ASCII Code 4. byte: das zeichen "A" 5. "r" 6. "c" zum hinweis auf nicht vorhandene deklaration, ich hab doch in meinem Record folgendes:
Delphi-Quellcode:
€dit: wenn ich etwas auf der Protocol Dokumentationsseite falsch entnommen, interpretiert oder überlesen habe, so
TMyPacket = packed record
id: Byte; length: Byte; username: array[0..15] of AnsiChar; // bzw. of Byte end; bitte ich um verständnis und um korrektur :D |
AW: TIdTCPServer Byte Packets (Indy10)
kommt niemand drauf?
|
AW: TIdTCPServer Byte Packets (Indy10)
Code:
Wenn ich das richtig interpretiere:
All packets begin with a single "Packet ID" byte. Listed packet size includes this byte. Packets are either "server to client", "client to server", or both. If not specified, assume that the packet can be sent both ways. There is no "length" field; for variable length packets, you must parse to the end to determine the length.
Paketaufbau: Id - Byte Size - Byte Data - Array of char Size beinhaltet die Gesamtlänge des Paketes. Wenn DArc übertragen wird sollte Size dann 6 sein. Grüße Klaus |
AW: TIdTCPServer Byte Packets (Indy10)
Ich denke so weit war ich schon, siehe eine antwort früher ...
Zitat:
|
AW: TIdTCPServer Byte Packets (Indy10)
Tja, die Packages gehen nunmal nicht so als "ein" Package raus.
Kleinere werden von Indy gerne mal zusammengefasst, was auch nicht unbedingt schlecht ist und alles was größer als soein TCP-Packet ist, wird nunmal aufgeteilt. Du kannst also im Server nur erstmal stur versuchen das Längenbyte zu lesen, und dann die entsprechende Anzahl an Datenbytes. Wenn du nicht blockierend lesen willst, dann wirst du haöt bis zum Eintreffen des nächsten/übernächsten/... Datenblocks warten müssen, bis das dann vollständig vorhanden und verarbeitbar ist. Oder man speichert sich alles Unvollständige, hängt die neuen Daten an, verarbeitet dann so weit, wie möglich und merkt sich den rest wieder, bis der nächste Block ankommt. PS:
Delphi-Quellcode:
Ein Problem, welches du bekommen könntest: Abgebrochene/fehlerhafte Übertragungen, wo dann eine Lücke entsteht und du eventuell nicht mehr dan Anfang der Datenblöcke findest ... dafür könnte man sich z.B. noch eine Startsequenz/-signaur einbauen.
TMyPacket = packed record
id: Byte; length: Byte; username: array[0..15] of AnsiChar; end; // entspricht zufällig TMyPacket = packed record id: Byte; username: String[16]; // das ist ein ShortString, die sind immer ANSI und mit einem vorangestellen Längenbyte end; |
AW: TIdTCPServer Byte Packets (Indy10)
Zitat:
Ich dachte mir, TCP regelt fehlerhafte Übertragungen. =P |
AW: TIdTCPServer Byte Packets (Indy10)
Und das funktioniert auch fehlerfrei?
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:48 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz