|
Registriert seit: 5. Jan 2005 Ort: Stadthagen 9.454 Beiträge Delphi 10 Seattle Enterprise |
#27
Das die Daten vertauscht sind steht doch lang und breit in der Dokumentation:
![]() Reply format
The reply always starts with FF FF FF FF 66 0A. The format is then a series of these server address blocks:
Da ich mir dieses Elend mit dem Auslesen und Schreiben nicht mehr ansehen kann, hier mal eine Unit, womit man dieses Pakete sehr einfach zusammenbauen und auch wieder auseinander nehmen kann. Kleine Demo vorweg (alles was einem unbekannt vorkommt ist in der Unit SourceQuery definiert):
Delphi-Quellcode:
Ausgabe von RealInfoRequest
:
program SimpleTests;
{$APPTYPE CONSOLE} {$R *.res} uses IdGlobal, IdUDPClient, StrUtils, SysUtils, SourceQuery in 'SourceQuery.pas'; procedure ParseInfoResponse( AResponse: TSourceQueryBytes ); var LID: SQUShort; LEDF: SQByte; begin Writeln( 'Parse-Data:' ); Writeln; Writeln( 'Protocol-Header ', AResponse.ReadLong ); Writeln( 'Packet-Header ', AResponse.ReadChar ); Writeln( 'Protocol ', AResponse.ReadByte ); Writeln( 'Name ', AResponse.ReadString ); Writeln( 'Map ', AResponse.ReadString ); Writeln( 'Folder ', AResponse.ReadString ); Writeln( 'Game ', AResponse.ReadString ); LID := AResponse.ReadUShort; Writeln( 'ID ', LID ); Writeln( 'Players ', AResponse.ReadByte ); Writeln( 'Max. Players ', AResponse.ReadByte ); Writeln( 'Bots ', AResponse.ReadByte ); Writeln( 'Server Type ', AResponse.ReadChar ); Writeln( 'Environment ', AResponse.ReadChar ); Writeln( 'Visibility ', AResponse.ReadByte ); Writeln( 'VAC ', AResponse.ReadByte ); // Testen auf "The Ship" if ( LID >= 2400 ) and ( LID <= 2499 ) then begin Writeln( 'Mode ', AResponse.ReadByte ); Writeln( 'Witnesses ', AResponse.ReadByte ); Writeln( 'Duration ', AResponse.ReadByte ); end; Writeln( 'Version ', AResponse.ReadString ); if not AResponse.Eof then begin LEDF := AResponse.ReadByte; Writeln( 'EDF ', LEDF ); if LEDF and $80 = $80 then begin Writeln( 'Port ', AResponse.ReadShort ); end; if LEDF and $10 = $10 then begin Writeln( 'SteamID ', AResponse.ReadLongLong ); end; if LEDF and $40 = $40 then begin Writeln( 'Port ', AResponse.ReadShort ); Writeln( 'Name ', AResponse.ReadString ); end; if LEDF and $20 = $20 then begin Writeln( 'Keywords ', AResponse.ReadString ); end; if LEDF and $01 = $01 then begin Writeln( 'GameID ', AResponse.ReadLongLong ); end; end; end; procedure TestInfoResponse; var LResponse: TSourceQueryBytes; begin Writeln( 'Example response for Counter Strike: Source:' ); Writeln; LResponse.SetData( {AData} HexStrToBytes( {AHexStr} StringReplace( {} 'FF FF FF FF 49 02 67 61 6D 65 32 78 73 2E 63 6F' + {} '6D 20 43 6F 75 6E 74 65 72 2D 53 74 72 69 6B 65' + {} '20 53 6F 75 72 63 65 20 23 31 00 64 65 5F 64 75' + {} '73 74 00 63 73 74 72 69 6B 65 00 43 6F 75 6E 74' + {} '65 72 2D 53 74 72 69 6B 65 3A 20 53 6F 75 72 63' + {} '65 00 F0 00 05 10 04 64 6C 00 00 31 2E 30 2E 30' + {} '2E 32 32 00', {OldPattern} ' ', {NewPattern} '', {Flags} [rfReplaceAll] ) ) ); ParseInfoResponse( LResponse ); end; procedure RealInfoRequest; var LRequest, LResponse: TSourceQueryBytes; LUdp: TIdUDPClient; LBuffer: TIdBytes; LResponseSize: Integer; begin // Prepare Request LRequest.WriteLong( SQ_SIMPLEPACKET_PROTOCOL_HEADER ); LRequest.WriteByte( SQ_INFO_REQUEST_HEADER ); LRequest.WriteString( 'Source Engine Query' ); Writeln( 'REQUEST-DATA:' ); Writeln; Writeln( LRequest.ToString ); Writeln; LBuffer := LRequest.GetData; LUdp := TIdUDPClient.Create( nil ); try // Send Request Write( 'Sending ... ' ); LUdp.SendBuffer( '5.45.97.44', 2301, LBuffer ); // Receive Response SetLength( LBuffer, SQ_PACKET_MAXSIZE ); Write( 'Receiving ... ' ); LResponseSize := LUdp.ReceiveBuffer( LBuffer ); Writeln( LResponseSize, ' Bytes' ); SetLength( LBuffer, LResponseSize ); Writeln; finally LUdp.Free; end; Writeln( 'RESPONSE-DATA:' ); Writeln; Writeln( DumpBuffer( LBuffer ) ); Writeln; // Parse Response LResponse.SetData( LBuffer ); ParseInfoResponse( LResponse ); end; procedure RealMasterQueryRequest; var LRequest, LResponse: TSourceQueryBytes; LBuffer: TIdBytes; LBufferSize: Integer; LUdp: TIdUDPClient; LServerAddress: TSQServerAddressBlock; LCount, LRetries: Integer; begin LServerAddress.IP1 := 0; LServerAddress.IP2 := 0; LServerAddress.IP3 := 0; LServerAddress.IP4 := 0; LServerAddress.Port := 0; LUdp := TIdUDPClient.Create( nil ); try LCount := 0; repeat // Daten abrufen ... LRequest.Clear; LRequest.WriteByte( $31 ); // Message Type LRequest.WriteByte( SQ_REGIONCODE_RESTOFTHEWORLD ); // Region Code LRequest.WriteString( LServerAddress.ToString ); // IP-Address LRequest.WriteString( '\gamedir\arma2arrowpc' ); // Filter LBuffer := LRequest.GetData; // Send Request LUdp.SendBuffer( 'hl2master.steampowered.com', 27011, LBuffer ); LRetries := 0; repeat if LRetries >= 3 then raise Exception.Create( 'Too many retries' ); SetLength( LBuffer, SQ_PACKET_MAXSIZE ); LBufferSize := LUdp.ReceiveBuffer( LBuffer, 2000 ); Inc( LRetries ); until LBufferSize > 0; SetLength( LBuffer, LBufferSize ); LResponse.SetData( LBuffer ); Assert( LResponse.ReadLong = SQ_SIMPLEPACKET_PROTOCOL_HEADER ); Assert( LResponse.ReadByte = $66 ); Assert( LResponse.ReadByte = $0A ); // Parse the Server-Addresses while not LResponse.Eof do begin Inc( LCount ); LServerAddress.IP1 := LResponse.ReadByte; LServerAddress.IP2 := LResponse.ReadByte; LServerAddress.IP3 := LResponse.ReadByte; LServerAddress.IP4 := LResponse.ReadByte; LServerAddress.Port := swap( LResponse.ReadUShort ); // swap weil die Doku das sagt Writeln( LCount:7, '. ', LServerAddress.ToString ); end; until ( LServerAddress.ToString = '0.0.0.0:0' ); // ... bis die leere Adresse zurückkommt finally LUdp.Free; end; end; begin try TestInfoResponse; RealInfoRequest; RealMasterQueryRequest; except on E: Exception do Writeln( E.ClassName, ': ', E.Message ); end; ReadLn; end.
Code:
In der ganz kurzen Form (ohne Dump und Kommentare)) sieht ein Request dann wie folgt aus
REQUEST-DATA:
FF FF FF FF 54 53 6F 75 72 63 65 20 45 6E 67 69 ÿÿÿÿTSource Engi 6E 65 20 51 75 65 72 79 00 ne Query. Sending ... Receiving ... 196 Bytes RESPONSE-DATA: FF FF FF FF 49 11 5B 4C 2D 54 2D 53 5D 20 45 70 ÿÿÿÿI.[L-T-S] Ep 6F 63 68 20 4F 72 69 67 69 6E 73 20 28 31 2E 30 och Origins (1.0 2E 35 2E 31 2F 31 32 35 35 34 38 29 00 54 61 76 .5.1/125548).Tav 69 00 61 72 6D 61 32 61 72 72 6F 77 70 63 00 44 i.arma2arrowpc.D 61 79 5A 20 45 70 6F 63 68 20 4F 72 69 67 69 6E ayZ Epoch Origin 73 00 8A 84 01 19 00 64 77 00 00 31 2E 36 33 2E s.??...dw..1.63. 31 32 35 35 34 38 00 B1 FE 08 01 CC 2C AF 75 14 125548.±þ..Ì,¯u. 40 01 62 74 2C 72 31 36 33 2C 6E 31 32 35 35 34 @.bt,r163,n12554 38 2C 73 37 2C 69 31 2C 6D 66 2C 6C 66 2C 76 66 8,s7,i1,mf,lf,vf 2C 64 74 2C 74 63 6F 6F 70 2C 67 36 35 35 34 35 ,dt,tcoop,g65545 2C 63 32 31 34 37 34 38 33 36 34 37 2D 32 31 34 ,c2147483647-214 37 34 38 33 36 34 37 2C 70 77 2C 00 8A 84 00 00 7483647,pw,.??.. 00 00 00 00 .... Parse-Data: Protocol-Header -1 Packet-Header I Protocol 17 Name [L-T-S] Epoch Origins (1.0.5.1/125548) Map Tavi Folder arma2arrowpc Game DayZ Epoch Origins ID 33930 Players 1 Max. Players 25 Bots 0 Server Type d Environment w Visibility 0 VAC 0 Version 1.63.125548 EDF 177 Port 2302 SteamID 90094488230087681 Keywords bt,r163,n125548,s7,i1,mf,lf,vf,dt,tcoop,g65545,c2147483647-21474 83647,pw, GameID 33930
Delphi-Quellcode:
Der komplette Source im Anhang
procedure InfoRequest;
var LRequest, LResponse: TSourceQueryBytes; LUdp: TIdUDPClient; LBuffer: TIdBytes; LResponseSize: Integer; begin LRequest.WriteLong( SQ_SIMPLEPACKET_PROTOCOL_HEADER ); LRequest.WriteByte( SQ_INFO_REQUEST_HEADER ); LRequest.WriteString( 'Source Engine Query' ); LBuffer := LRequest.GetData; LUdp := TIdUDPClient.Create( nil ); try LUdp.SendBuffer( '5.45.97.44', 2301, LBuffer ); SetLength( LBuffer, SQ_PACKET_MAXSIZE ); LResponseSize := LUdp.ReceiveBuffer( LBuffer ); SetLength( LBuffer, LResponseSize ); finally LUdp.Free; end; LResponse.SetData( LBuffer ); ParseInfoResponse( LResponse ); end;
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 (26. Feb 2015 um 21:42 Uhr) |
||||||||||||
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs 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
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |