AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Query an Gameserver

Query an Gameserver

Ein Thema von Flodding · begonnen am 18. Feb 2015 · letzter Beitrag vom 1. Nov 2015
Antwort Antwort
Medium

Registriert seit: 23. Jan 2008
3.688 Beiträge
 
Delphi 2007 Enterprise
 
#1

AW: Query an Gameserver

  Alt 19. Feb 2015, 16:50
Nein, kein Array. Du bekommst strukturierte Daten, und in dieser Struktur kommen mehrere Typen gemischt vor. Deine ganze Umwandlerei in Strings schmeiss doch einfach mal bitte komplett weg, das führt zu nichts, weil du eben nicht einen String zurück gesendet bekommst. Es ist schlicht die völlig falsche Interpretation der Daten.
Wie die Daten zu interpretieren sind, wird in dem Link zu der Steam Seite haarklein aufgelistet, die weiter vorne hier verlinkt wurde. Da stehen ausführlich ALLE Informationen, die man braucht um die Antwortpakete richtig zu interpretieren. Und wenn alle Stricke reissen, kannst du den fix und fertigen PHP code, den du selbst geposted hast, nach Delphi übersetzen und aus der damit interpretierten Struktur die für dich interessanten Werte nutzen. Komfortabler geht es einfach nicht mehr. Es ist alles da an Infos, sogar eine Beispielimplementierung.
Du musst einfach nur mal von dem Trip runter kommen, dass da Strings kommen. Ist nicht so. Das ist keine XML Datei. Komische Zeichen bekommst du nur, weil du die Daten komplett falsch interpretierst. Ja, es sind Abschnitte drin, die einzelne Strings ergeben. Aber das ist halt nicht für alles so.
Mache dich am besten erstmal mit einer Hand voll Grundlagen zu Datentypen und der internen Darstellung von Ganzzahlen, Texten und Gleitpunktzahlen vertraut. Das ist absolut elementares Wissen, dass du beim Programmieren praktisch jede Minute brauchst. Es ist also nichtmals so, dass das gelernte so speziell ist, dass es nur auf dein aktuelles Problem zutrifft. Das krasse Gegenteil ist der Fall.
"When one person suffers from a delusion, it is called insanity. When a million people suffer from a delusion, it is called religion." (Richard Dawkins)
  Mit Zitat antworten Zitat
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#2

AW: Query an Gameserver

  Alt 22. Feb 2015, 10:32
Hallo nochmal.

Also ich hab jetzt jede Menge ausprobiert und wollte auch anfangen den Code von PHP nach DELPHI zu portieren. Daran scheitere ich jedoch komplett, da ich den PHP-Code nicht 100% verstehe.

Des Weiteren ist was von Kompression aufgekreuzt...

In diesem Script wird geschaut ob der empfangene Buffer "compressed" ist oder nicht.
https://github.com/xPaw/PHP-Source-Q...cket.class.php

Ich weiss nicht wie ich damit umgehen soll. Ich hab nur rausgefunden, dass es scheinbar eine ZLIB Kompression ist.

Weiterhin bin ich soweit, dass ich jetzt die ersten 6 empfangenen Informationen sicher empfangen kann. Das wären dann: Header, Protocol, Name, Map, Folder, Game

Ab der 6ten bzw. 7ten Information (Map ja oder nein) hapert es jedoch, denn dort steht eine doppel"00" dafür, dass keine Spieler auf dem Server sind und dann erkennt mein Programm aber nur die "00" als Ende der Information und überspringt diese.

hier einmal die empfangenen Daten:

Mit Map:
Code:
49; Header
11; Protokol
5B4C2D542D535D2045706F6368204F726967696E732028312E302E352E312F3132353534382900; Name
5461766900; Map
61726D61326172726F77706300; Folder
4461795A2045706F6368204F726967696E7300; Game
8A8400; Diese beiden Zeilen sollten eigentlich
3300;   Eine Zeile sein. 00 Problem. Sie beinhalten die ID (33930), Anzahl Spieler und Max Spieler
647700; Server Type / Environment
00; ?? Bots ?? Kann ich leider nicht testen, da in diesem Spiel Bots nicht erkannt werden.
312E36332E31323535343800; Spielversion
B1FE08031027D86514400162742C723136332C6E3132353534382C73372C69312C6D662C6C662C76662C64742C74636F6F702C6736353534352C63323134373438333634372D323134373438333634372C70772C00; GameTags
8A8400; Game ID , sollte umgewandelt "33930" ergeben. tut es auch nicht.
00;
00;
00;
00;
00;
jetzt das ganze mit Spieler und Map
Code:
49;
11;
5B4C2D542D535D2045706F6368204F726967696E732028312E302E352E312F3132353534382900;
5461766900;
61726D61326172726F77706300;
4461795A2045706F6368204F726967696E7300;
8A84013300; Hier wurde Jetzt nicht getrennt, weil "00" zu "01" wude
64770100; Hier ist noch Password hinzugekommen. (getestet)
312E36332E31323535343800;
B1FE0801B0DD6A6614400162742C723136332C6E3132353534382C73332C69312C6D662C6C662C76662C64742C74636F6F702C6736353534352C63323134373438333634372D323134373438333634372C70772C00;
8A8400;
00;
00;
00;
00;
00;
Die Unterschiede konnte ich leider nicht FETT markieren, habe sie aber kommentiert.

Also das Sortieren der Bytes anhand der "00"en schlägt in diesem Fall fehl.

Jetzt würde ich gerne wissen was ICH falsch mache oder wie ich es besser machen kann...

Anbei nochmal der Quellcode mit dem ich die Informationen bekomme.

Delphi-Quellcode:
procedure TForm4.Button1Click(Sender: TObject);
var
A: TStringList;
x: array[0..25] of byte;
y: array[0..1400] of byte;
i: integer;
buff_delemitted: string;
hexzahl: string;
dezimalzahl: integer;

server_protocol: string;
map_name: string;
server_name: string;
folder_name: string;
game_name: string;
game_id: string;
server_type: string;
server_environment: string;
max_players: string;

begin
memo1.Clear;
udp1.RemotePort:= '5.45.97.44';
udp1.RemoteHost:= '2302';
udp1.Active:= true;

x[0]:= $FF;
x[1]:= $FF;
x[2]:= $FF;
x[3]:= $FF;
x[4]:= $54;
x[5]:= $53;
x[6]:= $6F;
x[7]:= $75;
x[8]:= $72;
x[9]:= $63;
x[10]:= $65;
x[11]:= $20;
x[12]:= $45;
x[13]:= $6E;
x[14]:= $67;
x[15]:= $69;
x[16]:= $6E;
x[17]:= $65;
x[18]:= $20;
x[19]:= $51;
x[20]:= $75;
x[21]:= $65;
x[22]:= $72;
x[23]:= $79;
x[24]:= $00;

udp1.SendBuf(x,sizeof(x));

udp1.ReceiveBuf(y,sizeof(y));

for i := 4 to sizeof(y) - 1 do begin

  if (IntToHex(y[i], 2) = '49') then
  begin
    buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';'
  end
  else
  if i = 5 then
  begin
    buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';'
  end
  else
  if (IntToHex(y[i], 2) = '00') then
  begin
    buff_delemitted := buff_delemitted + IntToHex(y[i], 2) + ';'
  end
  else
  begin
    buff_delemitted := buff_delemitted + IntToHex(y[i], 2)
  end;

  Application.ProcessMessages;
end;

Memo1.Text := buff_delemitted;

A := TStringList.Create;
try
Split(';', buff_delemitted, A) ;
  server_protocol := inttostr(hextoint(a[1]));
  server_name := HexStrToString(a[2]);
  map_name := HexStrToString(a[3]);
  folder_name := HexStrToString(a[4]);
  game_name := HexStrToString(a[5]);

  server_type := HexStrToString(a[7])[1];
  server_environment := HexStrToString(a[7])[2];

  max_players := HexStrToString(a[8]);

finally
  A.Free;
end;

end;
MFG
Flo
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#3

AW: Query an Gameserver

  Alt 22. Feb 2015, 11:45
Du willst dir anscheinend nicht die Dokumentation von Valve durchlesen. Dass ist natürlich fatal und daher gebe ich dir nur noch einmal den Rat, dieses dringend nachzuholen.

Ganz oben steht da nämlich die Definition der Data Types
NameDescriptionByte-Länge
byte8 bit character or unsigned integer1 Byte
short16 bit signed integer2 Byte
long32 bit signed integer4 Byte
float32 bit floating point4 Byte
long long64 bit unsigned integer8 Byte
stringvariable-length byte field, encoded in UTF-8, terminated by 0x00solange ein Byte lesen, bis man $00 liest

Wenn ich dann lese, dass du die ID (Steam Application ID of game) da vermutest
Code:
8A8400; Diese beiden Zeilen sollten eigentlich
3300;  Eine Zeile sein. 00 Problem. Sie beinhalten die ID (33930), Anzahl Spieler und Max Spieler
dann hast du die Dokumentation nämlich nicht gelesen.

Wenn ich jetzt mal deine Daten dem Response Format laut Dokumentation zuordne, dann erhalte ich
FieldTypeBytesRAW-Data
Headerbyte149
Protocolbyte111
Namestringvar5B4C2D542D535D2045706F6368204F726967696E732028312E302E352E312F3132353534382900
Mapstringvar5461766900
Folderstringvar61726D61326172726F77706300
Gamestringvar4461795A2045706F6368204F726967696E7300
IDshort28A84
Playersbyte100
Max. Playersbyte133
Botsbyte100
......... 
Vergleiche das mit deinen Angaben und du solltest den Fehler feststellen.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)

Geändert von Sir Rufo (22. Feb 2015 um 11:48 Uhr)
  Mit Zitat antworten Zitat
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#4

AW: Query an Gameserver

  Alt 22. Feb 2015, 12:02
Also ist meine Angehensweise total falsch.

Ich muss Die Reihenfolge der Empfangenen Daten beachten um dann gezielt die Bytes auszulesen.

Ich habe ehrlich gesagt die ganze Zeit nicht die Längenangaben hintendran beachtet und somit bin ich von völlig falschen längen ausgegangen.

Theoretisch müsste ich in etwa so interpretieren:

Header: Lese 1tes Byte und wandele um,
Protocol: Lese 2tes Byte und wandele um,
Name: Fang an zu lesen nach 2tem Byte und stoppe bei erstem "00" , merke dir wo du aufgehört hast zu lesen!!!
Map: Lese weiter wo du vorher aufgehört hast und weiter bis zum nächsten "00"; merk dir wieder die Endposition.
Folder: weiter "00" bis "00" lesen, merken,
Game: weiter "00" bis "00" lesen, merken,
ID: Lese von der LETZTEN Position 2 Bytes weiter und wandele um, merk dir neue Position,
Players: Lese 1 weiteres Byte, wandele um und merk dir Position,
Max. Players: ....... und so weiter.


Korrekt?

EDIT:

Die ID : 8A84 sollte umgewandelt 33930 ergeben. Tut es aber nicht egal in was ich umwandel. HextoStr gibt Kryptisches, HextoInt gibt eine falsche Zahl: 35460.
Flo

Geändert von Flodding (22. Feb 2015 um 12:05 Uhr) Grund: Frage wegen GAMEID
  Mit Zitat antworten Zitat
BadenPower

Registriert seit: 17. Jun 2009
616 Beiträge
 
#5

AW: Query an Gameserver

  Alt 22. Feb 2015, 12:16
Die ID : 8A84 sollte umgewandelt 33930 ergeben. Tut es aber nicht egal in was ich umwandel. HextoStr gibt Kryptisches, HextoInt gibt eine falsche Zahl: 35460.
Das sagt mir, dass Du nie versucht hast 33930 in ein Hex umzuwandeln, denn dann hättest Du gesehen , dass 33930 ToHex-> 848A ist.

Na, fällt Dir etwas auf?
Programmieren ist die Kunst aus Nullen und Einsen etwas sinnvollen zu gestalten.
Der bessere Künstler ist allerdings der Anwender, denn dieser findet Fehler, welche sich der Programmierer nicht vorstellen konnte.
  Mit Zitat antworten Zitat
Flodding

Registriert seit: 26. Dez 2007
Ort: Kiel
121 Beiträge
 
Turbo Delphi für Win32
 
#6

AW: Query an Gameserver

  Alt 22. Feb 2015, 12:18
ja das habe ich natürlich probiert...

von SIGNED INT to HEX funktionierts ja auch.

aber von HEX to SIGNED INT häng ich. ich bekomms nur in INT gewandelt und das gibt dann den falschen wert.
Flo
  Mit Zitat antworten Zitat
Benutzerbild von Sir Rufo
Sir Rufo

Registriert seit: 5. Jan 2005
Ort: Stadthagen
9.454 Beiträge
 
Delphi 10 Seattle Enterprise
 
#7

AW: Query an Gameserver

  Alt 22. Feb 2015, 13:17
Es ist erheblich einfacher als du denkst, aber du musst eben etwas umdenken

Zunächst einmal schaust du dir die Datentypen an, die Valve da vorgibt und suchst dir die passenden Delphi-Typen dazu heraus
http://docwiki.embarcadero.com/RADSt...Der_Typ_Single

Dann könnte man das hier bauen
Delphi-Quellcode:
type
  TValveByte = Byte; {8 bit character or unsigned integer}
  TValveShort = SmallInt; {16 bit signed integer}
  TValveLong = Integer; {32 bit signed integer}
  TValveFloat = Single; {32 bit floating point}
  TValveLongLong = Cardinal; {64 bit unsigned integer}
Jetzt gibt es in Delphi auch so nette Sachen wie Delphi-Referenz durchsuchenTStream und der kann Delphi-Referenz durchsuchenTStream.WriteData und (viel Spanier hier) Delphi-Referenz durchsuchenTStream.ReadData.

Du bekommst ja eine Handvoll Bytes und die kann man in einen Delphi-Referenz durchsuchenTBytesStream packen und dann liest man ganz gemütlich die Daten heraus.

Hier mal ein kleines Beispiel zum Starten:
Delphi-Quellcode:
const
  SIMPLE_RESPONSE_HEADER : TValveLong = $FFFFFFFF;
  MULTIPACKET_RESPONSE_HEADER : TValveLong = $FFFFFFFE;

procedure Foo( AResponse : TBytes );
var
  LResponseStream : TStream;
  LHeader : TValveLong;
begin
  LResponseStream := TBytesStream.Create( AResponse );
  try
    LResponseStream.ReadData( LHeader ); // Wir lesen den 4-Byte Header
    case LHeader of
      SIMPLE_RESPONSE_HEADER :
        WorkOnSimpleResponse( LResponseStream );
      MULTIPACKET_RESPONSE_HEADER :
        WorkOnMultiPacketResponse( LResponseStream );
    else
      raise Exception.CreateFmt( 'Unknown Header Value %8.8x', [LHeader] );
    end;
  finally
    LResponseStream.Free;
  end;
end;
Wie du sehen kannst, vermeide ich auf Teufel komm raus, irgendwo im Quelltext mit Magic Values zu arbeiten.

Wenn irgendein Wert eine bestimmte Bedeutung hat, dann definiert man sich einen Konstante und verwendet diese Konstante im Quelltext. Dann bleibt das auch immer schön lesbar.
Kaum macht man's richtig - schon funktioniert's
Zertifikat: Sir Rufo (Fingerprint: ‎ea 0a 4c 14 0d b6 3a a4 c1 c5 b9 dc 90 9d f0 e9 de 13 da 60)
  Mit Zitat antworten Zitat
Antwort Antwort

 
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 02:54 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