HL2 Server abfragen

Übersicht BlitzMax, BlitzMax NG Allgemein

Neue Antwort erstellen

 

gamble

Betreff: HL2 Server abfragen

BeitragSo, Mai 22, 2005 14:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi,

ich habe mir vorgenommen mal ein kleines Programm zu schreiben, mit welchem man Infos von einem HL2 Server angezeigt bekommt. Dazu muss ich zuerst folgendes an den Server schicken:

UINT32 0xFFFFFFFF
BYTE 0x54

Ich habe es im Moment wie folgt gelöst:

BlitzBasic:

WriteInt STREAM,$FFFFFFFF
WriteByte STREAM,$54
SendUDPMsg(STREAM,ServerIP,ServerPort)


Bekomme jedoch keine Antwort. Ich ahne schon, dass der Server mich einfach nicht versteht. Sobald ich aber ein 0x vor beide Werte anhänge, bekomme ich was von "Unknow identifier: x ...". Wie kann ich das jetzt lösen?
 

gamble

BeitragSo, Mai 22, 2005 18:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Weiß zwar nicht was da los ist, auf jedenfall funktioniert das Beispiel da oben jetzt. Dafür habe ich jetzt ein anderes Problem:

Ich habe den Integer, das Kontrollbyte, die Protokollversion und den Servernamen ohne Probleme ausgelesen. Wenn ich ReadString dann aber nochmal anwenden, wird mir NICHTS ausgegeben, obwohl da noch genug im Stream drin liegt (das nächste wäre der Mapname, ebenfalls ein String). Warum klappt das nicht? Ist das vielleicht ein Bug in Bnet?

Vertex

BeitragSo, Mai 22, 2005 19:08
Antworten mit Zitat
Benutzer-Profile anzeigen
Sorry, ich verstehe nicht, was das Problem ist.

Strings jedenfalls haben ihr eigenes Format in BMax. Damit wird der Server sicher nix anfangen können.

Versuchs höchstens mal mit WriteLine statts WriteString.

mfg olli
vertex.dreamfall.at | GitHub
 

gamble

BeitragSo, Mai 22, 2005 19:28
Antworten mit Zitat
Benutzer-Profile anzeigen
Es geht ums lesen, nicht ums schreiben.

Das Problem ist folgendes: Ich lese aus dem Stream, und obwohl im Stream noch etwas drin ist (sein müsste), bekomme ich nichts ausgegeben.

Wenn ich ReadByte, Readint ... verwende dann bekomme ich wirre Zahlenkombinationen. Nur bei ReadString bekomme ich nichts zurück, obwohl da eigentlich ein String auf mich wartet.

Das die Strings ein anderes Format haben dürfte auch nicht wirklich der Grund sein, immerhin konnte ich den Server-Namen ja auch auslesen.

Jolinah

BeitragSo, Mai 22, 2005 19:33
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo, das liegt bestimmt am Stringformat. Hatte dafür extra mal ne Funktion geschrieben, habs leider beim Upgrade auf die neue BMax Version verloren Sad. Die CStrings oder zumindest .Net Strings arbeiten mit 7-Bit encoded Ints oder sowas.

Also vor dem eigentlichen String steht ja immer die Länge des Strings. Wenn der String 255 Zeichen lang ist hätte das ja genau in einem Byte Platz. Wenn der String aber länger ist brauchts 2 Bytes. Um nicht einfach fix 4 Bytes zu übertragen wenn diese gar nicht nötig wären hat man das mit diesem 7-Bit encoding gemacht. Damit kann man jedoch nur noch 128 in 1 Byte bringen, weil ein Teil des Bytes für diesen kleinen Algorythmus (oder wie man es nennen soll) verwendet wird. Da man aber meistens nicht ellenlange Texte übers Netzwerk überträgt in Spielen (meistens < 128 Zeichen) lohnt sich das ganze schon, da man jedesmal 3 Bytes einspart pro String. Wenn der String dann grösser ist werden einfach mehrere Bytes vorab geschickt.

Diese dynamische Anzahl an Vorab-Bytes macht dann BMax Probleme.

Vielleicht finde ich die Funktion irgendwo noch oder mache sie neu. Wenn nicht kannst du ja mal nach 7-Bit encoded Integers oder so suchen Wink


Edit: Soviel ich weiss muss man bei ReadString in BMax ja die Länge des Strings angeben. Das heisst man muss die Länge vorher manuell auslesen. Beim Servernamen war da vielleicht auch nur 1 Byte am Anfang, aber bei anderen Texten könnten es halt auch 2 oder 4 sein wegen der dynamischen Länge.
 

gamble

BeitragSo, Mai 22, 2005 19:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Urgh, das ist ägerlich ... Aber warum einfach, wenns auch kompliziert geht Rolling Eyes

Edit: Ah, Lösung! Ich habe vor das zweite ReadString einfach ein ReadByte gepackt. Jetzt wird mir der String auch angezeigt Wink

Edit 2: Soweit so gut. Jetzt muss ich nur noch die Länge der Strings herausfinden den ich lesen will. Das Byte was ich vorher ausgelesen hab, hat allerdings den Wert 0, obwohl der String selber 8 Zeichen hat. Wie komm ich denn jetzt an die Stringlänge ran?
  • Zuletzt bearbeitet von gamble am So, Mai 22, 2005 19:50, insgesamt 2-mal bearbeitet

Jolinah

BeitragSo, Mai 22, 2005 19:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Weil man damit Traffic einsparen kann, und somit auch Kosten Wink

Edit: Hab C Code gefunden, hier der BMax Code, sollte funktionieren (nicht getestet)

Code:

Function Read7BitInt(stream:TStream)
   Local _count:Int = 0
   Local _shift:Int = 0
   Local _counter:Int = 0
   Local _b:Byte = 0
   
   Repeat
      Try
         _b = ReadByte(stream)
      Catch Ex:Object
         Throw "Error reading 7 Bit encoded Integer"
      End Try
      
      _counter :+ 1
      
      If _counter > 4
         Throw "Overflow 7 Bit encoded Integer"
      EndIf
      
      _count = _count | (_b & $7F) Shl _shift
      _shift :+ 7

   Until (_b & $80) = 0
   
   Return _count
   
End Function


Anwendung:

Code:

Local length:Int = Read7BitInt(stream)
Local mystring:String = ReadString(stream, length)
 

gamble

BeitragSo, Mai 22, 2005 19:59
Antworten mit Zitat
Benutzer-Profile anzeigen
Bekomme gleich die Exception um die Ohren gehauen:

Overflow 7 Bit encoded Integer

Wink

Jolinah

BeitragSo, Mai 22, 2005 20:06
Antworten mit Zitat
Benutzer-Profile anzeigen
Ich hatte nen Fehler bei Repeat Until. Original wars do while. Das heisst du musst das Not einfach entfernen, siehe oben.

Edit: Hier noch das schreiben

Code:

Function Write7BitInt(stream:TStream, value:Int)
   While value >= $80
      WriteByte(stream, Byte((value | $80)) )
      value = value Shr 7
   Wend
   
   WriteByte(stream, Byte(value))
End Function


Code:

Local name:String = "Bla"
Write7BitInt(stream, Len(name))
WriteString(stream, name)
 

gamble

BeitragSo, Mai 22, 2005 20:10
Antworten mit Zitat
Benutzer-Profile anzeigen
Jo, danke. Nur das Ergebnis ist leider 0 - wie beim "normalen" ReadByte auch. Merkwürdig.

Jolinah

BeitragSo, Mai 22, 2005 20:19
Antworten mit Zitat
Benutzer-Profile anzeigen
Dann wirds wohl sonst ein Problem sein. Bist du sicher dass du alles entsprechend dem Protokoll von HL2 richtig gemacht hast?
 

gamble

BeitragSo, Mai 22, 2005 20:26
Antworten mit Zitat
Benutzer-Profile anzeigen
Eigentlich schon. Ich poste einfach mal den Code:

Code:

While True
   
      If RecvUDPMsg(STREAM) Then
      
         Local server:TS2A_INFO_SRC = New TS2A_INFO_SRC
         
         Readint(STREAM)
         
         server.Kontrollbyte = ReadByte(STREAM)
         
         server.Protokollversion = ReadByte(STREAM)
         
         server.Name = ReadString(STREAM,32)
         
         Local length = Read7BitInt(STREAM)
         
         Print ReadString(STREAM,length)
         
         End
         
      End If
   
   Wend


Das erste Readint beinhaltet einfach nur -1, die nächsten beiden Bytes beinhalten das Kontrollbyte und die Protokollversion. Dann folgt schon der Servername. Da ich im Moment nur teste, kenne ich die Länge aus dem Kopf (32 Zeichen). Ermitteln kann ich sie auch nich, da ich dann irgendwas von 100 erhalte. Danach halt der Mapname - da length aber 0 ist wird der nicht angezeigt.

Hier der Aufbau der Antwort vom Server. Vielleicht bekommt das ja wer zum laufen?

http://wiki.hlsw.de/wiki/index...eprotokoll

Jolinah

BeitragSo, Mai 22, 2005 20:34
Antworten mit Zitat
Benutzer-Profile anzeigen
Hm Interessant Wink

Kennst du grad eine Server-IP? Dann kann ich ja auch mal bisschen rumprobieren.
 

gamble

BeitragSo, Mai 22, 2005 20:40
Antworten mit Zitat
Benutzer-Profile anzeigen
Klar.

62.4.74.236:30900

Vertex

BeitragSo, Mai 22, 2005 21:22
Antworten mit Zitat
Benutzer-Profile anzeigen
Hi!

Zitat:
SzString: Null-Terminierte Zeichenkette



Code:
Local UDP:TUDPStream
Local Temp:String
Local Char:Byte

UDP = CreateUDPStream()

WriteInt UDP, $FFFFFFFF
WriteByte UDP, $54
SendUDPMsg UDP, IntIP("62.4.74.236"), 30900

Repeat
   If RecvUDPMsg(UDP) Then
      Print "OK: "+Hex(Readint(UDP))
      Print "Kontrollbyte: "+Chr(ReadByte(UDP))
      Print "Protokollversion: "+ReadByte(UDP)
      
      Repeat
         Char = ReadByte(UDP)
         If Char = 0 Then Exit
         Temp :+ Chr(Char)
      Forever
      Print "Servername: "+Temp
      
      Temp = ""
      Repeat
         Char = ReadByte(UDP)
         If Char = 0 Then Exit
         Temp :+ Chr(Char)
      Forever
      Print "Map Name: "+Temp
      
      Temp = ""
      Repeat
         Char = ReadByte(UDP)
         If Char = 0 Then Exit
         Temp :+ Chr(Char)
      Forever
      Print "Spielverzeichnis: "+Temp
      
      Temp = ""
      Repeat
         Char = ReadByte(UDP)
         If Char = 0 Then Exit
         Temp :+ Chr(Char)
      Forever
      Print "Spielname: "+Temp
      
      Print "ApplicationID: "+ReadShort(UDP)
      
      Print "Spielerzahl: "+ReadByte(UDP)
      Print "Maximale Spieleranzahl : "+ReadByte(UDP)
      Print "Anzahl der Bots : "+ReadByte(UDP)
      Print "Dedicated: "+Chr(ReadByte(UDP))
      Print "Betriebssystem: "+Chr(ReadByte(UDP))
      Print "Passwort: "+ReadByte(UDP)
      Print "Secure Valve Anti Cheat aktiviert?: "+ReadByte(UDP)
      
      Exit
   EndIf
Forever

CloseUDPStream(UDP)
End


Zitat:
OK: FFFFFFFF
Kontrollbyte: I
Protokollversion: 7
Servername: tRaSh ! http://trash.clan-4u.net
Map Name: de_dust
Spielverzeichnis: cstrike
Spielname: Counter-Strike: Source
ApplicationID: 240
Spielerzahl: 10
Maximale Spieleranzahl : 10
Anzahl der Bots : 0
Dedicated: d
Betriebssystem: l
Passwort: 0
Secure Valve Anti Cheat aktiviert?: 0


mfg olli
vertex.dreamfall.at | GitHub
 

gamble

BeitragSo, Mai 22, 2005 21:29
Antworten mit Zitat
Benutzer-Profile anzeigen
Wahnsinn, ich danke Dir ! Wink

Jolinah

BeitragSo, Mai 22, 2005 21:45
Antworten mit Zitat
Benutzer-Profile anzeigen
Achso Embarassed das erklärt natürlich alles ^^

Ich glaub ich muss mal meine C Kentnisse aufstocken.. kenn die ganzen Abkürzungen nicht alle auswendig Wink

PS: Hoffe das mit dem 7Bit encoded kann trotzdem wer brauchen Wink


Edit: Aber was ich nicht ganz verstehe ist wieso ich beim erforschen des Streams nicht alles empfangen habe...

Code:

Strict

Local server = IntIP("62.4.74.236")
Local port = 30900

Local udp = CreateUDPStream()

WriteInt(udp, $FFFFFFFF)
WriteByte(udp, $54)

SendUDPMsg(udp, server, port)

Local quit:Byte = False

Repeat

   If RecvUDPMsg(udp) <> 0
      While Not Eof(udp)
         Print Chr(ReadByte(udp))
      Wend
   EndIf

Until KeyHit(KEY_ESCAPE) Or quit = True

CloseUDPStream(udp)

End


Ausgabe:
Code:

ÿ
ÿ
ÿ
ÿ
I

t
R
a
S
h
 
!
 
h
t
t
p
:
/
/
t
r
a
s
h
.
c
l
a
n
-
4
u
.
n
e
t


Müsste aber doch noch weiter gehen, das heisst Eof kann man hier wohl vergessen.. wegen den Nullterminierten Strings Wink

Vertex

BeitragSo, Mai 22, 2005 21:56
Antworten mit Zitat
Benutzer-Profile anzeigen
Print bei BMax hat ein bug. Bei bestimmten Zeichen (ich glaube sogar Null-terminated selber), ist eine folgende Ausgabe via Print nichtmehr möglich.

mfg olli
vertex.dreamfall.at | GitHub

Jolinah

BeitragSo, Mai 22, 2005 22:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Naja funktioniert ja jetzt, auch wieder was dazu gelernt danke Very Happy
 

gamble

BeitragMo, Mai 23, 2005 13:09
Antworten mit Zitat
Benutzer-Profile anzeigen
Bin gerade dabei die Spieler vom Server auszulesen - musste dabei aber einen anderen Server abfragen, da der oben genannte im Moment leer ist. Dabei ist mir aufgefallen dass nicht alle Server auf den Request überhaupt antworten.

Bei manchen Servern bekomme ich nicht einmal den Servernamen (etc) zurück, bei einem anderen klappt dann zum Beispiel alles.

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Allgemein

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group