AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi Query an Gameserver
Thema durchsuchen
Ansicht
Themen-Optionen

Query an Gameserver

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

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 10:20
EDIT: Frage nach der Antwort gepostet.

Hallo!

Immernoch die "nicht erreichbar" Problematik.

Mein aktueller Code um die Verbindung aufzubauen:
Delphi-Quellcode:
  form4.udp1.RemoteHost:= '5.45.97.44';
  form4.udp1.RemotePort:= '2301';
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin

  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));

  form4.udp1.WaitForData(1000);
  if Length(buffer)<1 then
  begin
   form4.udp1.Close;
   exit;
  end;
Wenn der Port korrekt ist, wird 1 Sekunde gewartet und dann der "buffer" gelesen.

Ist der Port aber kein QueryPort:
Delphi-Quellcode:
  form4.udp1.RemoteHost:= '5.45.97.44';
  form4.udp1.RemotePort:= '1111'; // Port geändert
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin

  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));

  form4.udp1.WaitForData(1000);
  if Length(buffer)<1 then
  begin
   form4.udp1.Close;
   exit;
  end;
Das Programm hängt sich auf.
Ich hab schon nachgelesen und scheinbar hängt es sich nicht wirklich auf, sondern lauscht weiterhin und wartet auf Antwort.

Ich bin auf diese Option gestoßen:
form4.udp1.BlockMode := bmNonBlocking Damit soll das angeblich funktionieren, jedoch bekomme ich dann immer die Meldung vom "OnError"-Event, dass keine Verbindung aufgebaut werden konnte.
Delphi-Quellcode:
procedure TForm4.udp1Error(Sender: TObject; SocketError: Integer);
begin
showmessage('Could not connect. The server you are trying to query might be down');
udp1.Active:= false;
end;
Irgendwelche Ideen?
Flo
  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 25. Feb 2015, 10:38
Ich habe das OnError Event erstmal deaktiviert, weil der immer ausgelöst wurde wenn WaitForData zu lange gedauert hat.

Habs so ausprobiert jetzt:
Delphi-Quellcode:
  form4.udp1.RemoteHost:= form4.edit1.Text;
  form4.udp1.RemotePort:= form4.edit2.Text;
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin
  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  CheckTime := Now();
  form4.udp1.WaitForData(1000);

  if (SecondsBetween(Now(),CheckTime) <= 1) then
  begin
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
  i := 0;
  ...
  ...
Bleibt immernoch hängen und wartet nicht nur 1 Sekunde.
Flo
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 10:51
Ich habe das OnError Event erstmal deaktiviert, weil der immer ausgelöst wurde wenn WaitForData zu lange gedauert hat.

Habs so ausprobiert jetzt:
Delphi-Quellcode:
form4.udp1.WaitForData(1000);

  if (SecondsBetween(Now(),CheckTime) <= 1) then
  begin
  ...
Bleibt immernoch hängen und wartet nicht nur 1 Sekunde.
Warum hast Du nicht meine Werte übernommen.

Also

Delphi-Quellcode:
form4.udp1.WaitForData(5000);

  if (SecondsBetween(Now(),CheckTime) <= 1) then
  begin
  ...
Weil wenn der TimeOut nur 1 Sekunde (Wert 1000) sein soll, dann ist der Unterschied zwischen CheckTime und Now() in der If-Anweiung IMMER kleiner oder gleich 1 Sekunde.
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
 
#4

AW: Query an Gameserver

  Alt 25. Feb 2015, 10:57
Nachdem das OnError Event deaktiviert wurde, funktionierte dann auch "bmNonBlocking"

Der Workaround funktioniert zwar, aber die Abfragezeit ist mit 5 Sekunden etwas lang.
Delphi-Quellcode:
  form4.udp1.BlockMode := bmNonBlocking;
  form4.udp1.RemoteHost:= form4.edit1.Text;
  form4.udp1.RemotePort:= form4.edit2.Text;
  form4.udp1.Open;

  if form4.udp1.Connected then
  begin
  form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
  form4.udp1.WaitForData(250);
  form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
  i := 0;
Dies funktioniert so ohne extra Zeitüberprüfung. Ob Queryport offen oder eben nicht.
Flo

Geändert von Flodding (25. Feb 2015 um 10:58 Uhr) Grund: Checktime entfernt
  Mit Zitat antworten Zitat
BadenPower

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 11:04
Der Workaround funktioniert zwar, aber die Abfragezeit ist mit 5 Sekunden etwas lang.
Diese Zeit ist nur 5 Sekunden, wenn der Server oder Port nicht erreichbar ist. Ist er Erreichbar, dann rutscht es in Milisekunden durch.

Nachdem das OnError Event deaktiviert wurde, funktionierte dann auch "bmNonBlocking"
wenn ich den UdpSocket auf "bmNonBlocking" stelle, dann blockiert er nie. Aber ich bekomme in diesem Modus keine Daten.
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 25. Feb 2015, 11:09
Dies hier funktioniert bei mir:
Delphi-Quellcode:
procedure Get_A2S_INFO;
var
  request: TInfoRequest;
  response: TInfoResponse;
  buffer: TBufferArray;
  i: Integer;
  CheckTime: TDateTime;
begin
  request.RequestHeader := -1;
  request.PacketHeader := 'T';
  request.Payload := 'Source Engine Query'; // Von mir aus auch mit einer Konstante oder einem Ressourcestring
  request.Payload[19] := #0;

  form4.udp1.BlockMode := bmNonBlocking;
  form4.udp1.RemoteHost:= form4.edit1.Text;
  form4.udp1.RemotePort:= form4.edit2.Text;
  form4.udp1.Open;

  if form4.udp1.Connected then
    begin
    form4.Udp1.SendBuf(request, SizeOf(TInfoRequest));
    form4.udp1.WaitForData(250);
    form4.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
    i := 0;
    Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
    Move(buffer[i], response.PacketHeader, SizeOf(response.PacketHeader)); inc(i, SizeOf(response.PacketHeader));
    Move(buffer[i], response.Protocol, SizeOf(response.Protocol)); inc(i, SizeOf(response.Protocol));

    if response.ResponseHeader = -1 then
      begin
      response.Name := GetString(buffer, i);
      response.Map := GetString(buffer, i);
      response.Folder := GetString(buffer, i);
      response.Game := GetString(buffer, i);
      Move(buffer[i], response.ID, SizeOf(response.ID)); inc(i, SizeOf(response.ID));
      Move(buffer[i], response.Players, SizeOf(response.Players)); inc(i, SizeOf(response.Players));
      Move(buffer[i], response.MaxPlayers, SizeOf(response.MaxPlayers)); inc(i, SizeOf(response.MaxPlayers));
      Move(buffer[i], response.Bots, SizeOf(response.Bots)); inc(i, SizeOf(response.Bots));
      Move(buffer[i], response.ServerType, SizeOf(response.ServerType)); inc(i, SizeOf(response.ServerType));
      Move(buffer[i], response.Environment, SizeOf(response.Environment)); inc(i, SizeOf(response.Environment));
      Move(buffer[i], response.Visibility, SizeOf(response.Visibility)); inc(i, SizeOf(response.Visibility));
      Move(buffer[i], response.VAC, SizeOf(response.VAC)); inc(i, SizeOf(response.VAC));
      response.Version := GetString(buffer, i);
      Move(buffer[i], response.EDF, SizeOf(response.EDF)); inc(i, SizeOf(response.EDF));
      Move(buffer[i], response.EDFPort, SizeOf(response.EDFPort)); inc(i, SizeOf(response.EDFPort));
      Move(buffer[i], response.EDFSteamID, SizeOf(response.EDFSteamID)); inc(i, SizeOf(response.EDFSteamID));
      Move(buffer[i], response.EDFSpecPort, SizeOf(response.EDFSpecPort)); inc(i, SizeOf(response.EDFSpecPort));
      //response.EDFSpecName := GetString(buffer, i);
      response.EDFKeywords := GetString(buffer, i);
      Move(buffer[i], response.EDFGameID, SizeOf(response.EDFGameID)); inc(i, SizeOf(response.EDFGameID));

      form4.lblServerHeader.Caption := chr(response.PacketHeader);
      form4.lblServerProtocol.Caption := IntToStr(response.Protocol);
      form4.lblServerName.Caption := response.Name;
      form4.lblServerMap.Caption := response.Map;
      form4.lblServerFolder.Caption := response.Folder;
      form4.lblServerGame.Caption := response.Game;
      form4.lblServerID.Caption := inttostr(response.ID);
      form4.lblServerPlayers.Caption := IntToStr(response.Players);
      form4.lblServerMaxPlayers.Caption := IntToStr(response.MaxPlayers);
      form4.lblServerBots.Caption := IntToStr(response.Bots);
      form4.lblServerType.Caption := chr(response.ServerType);
      form4.lblServerEnvironment.Caption := chr(response.Environment);
      form4.lblServerVisibility.Caption := inttostr(response.Visibility);
      form4.lblServerVAC.Caption := IntToStr(response.VAC);
      form4.lblServerVersion.Caption := response.Version;
      end
      else
      form4.lblServerName.Caption := 'Server nicht erreichbar';
  end;
end;
Das Error Event:
Delphi-Quellcode:
procedure TForm4.udp1Error(Sender: TObject; SocketError: Integer);
begin
//showmessage('Could not connect. The server you are trying to query might be down');
//udp1.Active:= false;
end;
Flo
  Mit Zitat antworten Zitat
Flodding

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

AW: Query an Gameserver

  Alt 25. Feb 2015, 14:32
Die Sekundenanzeige bei Der Playerinfo will auch nicht so ganz.

Delphi-Quellcode:
TPlayerResponse = record
  ResponseHeader: Integer;
  PacketHeader: Byte;
  Challenge: Integer;
  PlayerCount: Byte;
  PlayerIndex: Byte;
  PlayerName: String;
  PlayerScore: Integer;
  PlayerDuration: Integer;
end;
Delphi-Quellcode:
procedure Get_PLAYER_INFO;
var
  request: TInfoRequest;
  response: TPlayerResponse;
  buffer: TBufferArray;
  i: Integer;
  y: integer;
  PlayerList: TTreeNode;
begin
  request.RequestHeader := -1;
  request.PacketHeader := 'U';
  request.Payload := 'FFFFFFFF';

  Form1.udp1.BlockMode := bmNonBlocking;
  Form1.udp1.RemoteHost:= Form1.edit1.Text;
  Form1.udp1.RemotePort:= Form1.edit2.Text;
  Form1.udp1.Open;

  if (Form1.udp1.Connected) then
    begin
    Form1.Udp1.SendBuf(request, SizeOf(TInfoRequest));
    Form1.udp1.WaitForData(250);
    Form1.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
    //Challenge aus Buffer lesen
    i := 0;
    Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
    Move(buffer[i], response.PacketHeader, SizeOf(response.PacketHeader)); inc(i, SizeOf(response.PacketHeader));
    Move(buffer[i], response.Challenge, SizeOf(response.Challenge)); inc(i, SizeOf(response.Challenge));
    if chr(response.PacketHeader) = 'Athen
      begin
      //Challende in den PayLoad schreiben
      request.Payload[0] := chr(buffer[5]);
      request.Payload[1] := chr(buffer[6]);
      request.Payload[2] := chr(buffer[7]);
      request.Payload[3] := chr(buffer[8]);
      //A2S_PLAYER request mit Challenge senden
      Form1.Udp1.SendBuf(request, SizeOf(TInfoRequest));
      Form1.udp1.WaitForData(250);
      Form1.Udp1.ReceiveBuf(buffer, SizeOf(buffer));
      i := 0;
      Move(buffer[i], response.ResponseHeader, SizeOf(response.ResponseHeader)); inc(i, SizeOf(response.ResponseHeader));
      Move(buffer[i], response.PacketHeader, SizeOf(response.PacketHeader)); inc(i, SizeOf(response.PacketHeader));
      if chr(response.PacketHeader) = 'Dthen
        begin
        Move(buffer[i], response.PlayerCount, SizeOf(response.PlayerCount)); inc(i, SizeOf(response.PlayerCount));
        Form1.TreeView1.Items.Clear;
        for y := 0 to response.PlayerCount - 1 do
          begin
          Move(buffer[i], response.PlayerIndex, SizeOf(response.PlayerIndex)); inc(i, SizeOf(response.PlayerIndex));
          response.PlayerName := GetString(buffer, i);
          Move(buffer[i], response.PlayerScore, SizeOf(response.PlayerScore)); inc(i, SizeOf(response.PlayerScore));
          Move(buffer[i], response.PlayerDuration, SizeOf(response.PlayerDuration)); inc(i, SizeOf(response.PlayerDuration));

          PlayerList := Form1.TreeView1.Items.Add(Nil, response.PlayerName);
          Form1.TreeView1.Items.AddChild(PlayerList, 'ID: ' + IntToStr(response.PlayerIndex));
          Form1.TreeView1.Items.AddChild(PlayerList, 'Kills: ' + IntToStr(response.PlayerScore));
          Form1.TreeView1.Items.AddChild(PlayerList, 'Seconds: ' + IntToStr(response.PlayerDuration));

          Application.ProcessMessages;
          end;
        end;
      end;
    end;
form1.TreeView1.FullExpand;
Form1.udp1.Active := false;
end;
Lese ich die Zeit flasch aus?
Flo
  Mit Zitat antworten Zitat
Benutzerbild von BUG
BUG

Registriert seit: 4. Dez 2003
Ort: Cottbus
2.094 Beiträge
 
#8

AW: Query an Gameserver

  Alt 25. Feb 2015, 10:44
Da es mir Schmerzen verursacht, es immer wieder zu lesen: Es gibt keine UDP-Verbindung! UDP ist ein verbindungsloses Protokoll. Die Verbindung gibt es auf Anwendungsebene ... also das was du gerade programmierst.
Bezüglich des Fehlers: Guck dir mal den Errorcode an ... eventuell steht da nur so WSAEWOULDBLOCK drin.

Geändert von BUG (25. Feb 2015 um 10:53 Uhr)
  Mit Zitat antworten Zitat
Antwort Antwort

 

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 15:50 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