AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Netzwerke Delphi UDP -> Vom Server Daten lesen
Thema durchsuchen
Ansicht
Themen-Optionen

UDP -> Vom Server Daten lesen

Ein Thema von Airblader · begonnen am 31. Aug 2005 · letzter Beitrag vom 11. Sep 2005
Antwort Antwort
Benutzerbild von Airblader
Airblader

Registriert seit: 29. Okt 2004
Ort: Geislingen an der Steige
742 Beiträge
 
#1

UDP -> Vom Server Daten lesen

  Alt 31. Aug 2005, 18:23
Hi,

vielleicht eine (hoffentlich) etwas leichtere Problematik:
Ich kenne vom Server IP und Port.

Ich möchte nun an den Server eine Nachricht schicken. Danach werden autom. vom Server
Daten zurückgeschickt, die ich z.B. einfach in ein Memo lesen will.

Das ganze mit UDP.

ich hab nun mit TUDPSocket bei RemoteHost/Port die Daten eingegeben,
mittels Connect die Verbindung hergestellt und basierend auf diesen Thread folgendes getan,
um den Text zu lesen:

Delphi-Quellcode:
procedure ...
var RecBuf: string;
begin
  UdpSocket1.ReceiveBuf(RecBuf, UdpSocket1.BytesReceived);
  Form1.Memo1.Lines.Add(RecBuf);
end;
Also im Receiveevent.
Nun steht im genannten Thread, dass dieses Event nicht ausgelöst wird.
Da ich einfach mal davon ausgehe, dass meine Variante ansonsten funktionieren müsste, die frage:

Wie/Wo fange ich die Nachricht dann ab?

air
P.S.:
Gesendet wird übrigens in dem Stil:

Delphi-Quellcode:
var
  SendMsg: string;
begin
  SendMsg := '...';
  Form1.UdpSocket1.SendBuf(SendMsg, length(SendMsg));
end;
Ingo Bürk
Es nimmt der Augenblick, was Jahre geben.

Johann Wolfgang von Goethe
  Mit Zitat antworten Zitat
Arnulf

Registriert seit: 28. Okt 2004
Ort: Wien
271 Beiträge
 
#2

Re: UDP -> Vom Server Daten lesen

  Alt 1. Sep 2005, 21:27
Hi
naja das event wird ausgelöst, wenn du receivebuffer aufrufst.
Ist irgendwie nicht der sinn der sache.

Ich nehm mal an du willst von einem GameServer oder sowas ähnliches infos holen.
Genau das mach ich in meinem programm.
Jedenfalls kann ich dir sagen wie du das über indy machen würdest.
Wenn es dich interessiert, ich hab das auf 2 varianten gemacht.
1. ohne thread
hier liegt der vorteil in der linearität des programms, allerdings glaub ich verteufeln die methode viele .
2. mit thread
hier gibts auf jeden fall stress, wenn man noch nie mit threads gearbeitet hat.

In meiner Server application arbeite ich ohne thread weil ich ein sehr lineares programm hab, daß auf jeden fall auch auf den thread warten müsste, und das geht dann am sinn vom thread vorbei:

Delphi-Quellcode:
function GameServerExec( cmd : string ) : string;
         var ret : string;
             tryctr : integer;

         begin
               if fMain.cbxLogGS.Checked then
                  AddLogEntry( 'GameServerExec: send:' + cmd );
               cmd := 'rcon ' + fMain.edtRConPasswd.Text + #32 + cmd;

               tryctr := 0;
               ActiveSleep (5);

               fMain.UDPClient.Active := TRUE;
               ActiveSleep (5);

               ret := '';

               while (tryctr < 3)
               do
                     begin
                     try
                     fMain.UdpClient.Send( #255 + #255 + #255 + #255 + #2 + cmd );
                     except
                           AddLogEntry('Error on UDP Send');
                     end;

                     ActiveSleep (10);
                     try
                     ret := fMain.UdpClient.ReceiveString(); /// receive hängt
                     except
                           AddLogEntry('Error on UDP Receive');
                           ret := '';
                     end;

                     if ret = 'then
                     begin inc(tryctr);
                           if fMain.cbxLogGS.Checked then
                              AddLogEntry ('udp rsv failed trying again ' + InttoStr (tryctr));
                           ret := '';
                           ActiveSleep (20);
                     end
                     else tryctr := 3;

                     end; (* while *)

               fMain.UDPClient.Active := FALSE;

               if fMain.cbxLogGS.Checked then
                  AddLogEntry( 'GameServerExec response:' + ret );

               Application.ProcessMessages;
               GameServerExec := Copy( ret, 6, Length(ret)-5 );
        end;
Wichtig zu wissen ist wohl was ActiveSleep macht:

Delphi-Quellcode:
procedure ActiveSleep( MS : integer );
          var T : TDateTime;
              i : integer;

          begin //T := incmillisecond( Time, MS );
                For i := 1 to MS do
                    begin
                    application.ProcessMessages;
                    sleep (100)
                    end;

          end;
ActiveSleep ist eine routine die man immer wieder mal brauchen kann - immer wenn man keinen thread haben will, aber die application noch reagieren soll (auf events oder windows messages).

Die Variante mit thread ist wohl ungleich komplizierter.
Da ich mich selbst mit threads nicht gut auskenne, hab ich hier nur gebastelt - also bitte nicht schlagen, wenn das schrott ist .
Jedenfalls verwende ich das bei meinem Anticheat Client, da ich dort listen von gameserver verwalte und ich praktisch alle 1-2 sekunden ein update vom gameserver haben will:

Der Thread selbst:
Delphi-Quellcode:
function updatethread(p: Pointer): Integer;
var
  bShutDown: Boolean;
  s : string;
  i : integer;
begin
  bShutDown := False;
  while not bShutDown do
  begin
    // auf Client-Event warten
    WaitForSingleObject(EventReQuestSubmitted, INFINITE);
    bShutDown := UdpThreadCommand = UDPSHUTDOWN;
    UdpThreadCommand := '';
    if not bShutDown then
      begin
            fMain.udp.Active := TRUE;
            try
            fMain.udp.Send(#255 + #255 + #255 + #255 + #2 + 'getstatus');
            for i := 1 to 15 do
            begin if UdpThreadCommand = 'nextthen begin UdpThreadCommand := ''; s := ''; break; end;
                  s := fMain.udp.ReceiveString();
                  if s <> 'then break;
            end;
            except
            s := '';
            end;
            fMain.udp.Active := FALSE;
            if s = 'then s := 'TIMEOUT';
            SharedBuffer := s;
      end;
    // Client mitteilen, dass Request bearbeitet wurde
    InterLockedExchange(g_DataDelivered, 1);
  end;
  InterLockedExchange(g_DataDelivered, 1);
  result := 0;
end;
Hier sorgt ein Timer dafür, daß der thread immer wieder aktuallisiert, und im timer prüfe ich auch ob schon neue daten da sind:

Delphi-Quellcode:
procedure TfMain.tmrUpdateTimer(Sender: TObject);
begin
    if fMain.ClientSocket.Active then begin fMain.tmrUpdate.Enabled := FALSE; exit; end; // speziall für mein programm
    if (GsIp <> udp.Host) or (GsPort <> udp.Port) then // checken ob sich ip port ändern soll vom gameserver
    begin udp.Host := GsIp; // ist auch eher für mein programm wichtig
          udp.Port := GsPort; // weiß ja nicht was du vor hast
          exit;
    end;
    if ThreadID = 0 then // wenn der thread nicht läuft, darf auch der timer nicht laufen.
        begin tmrUpdate.Enabled := FALSE; exit; end;
    if InterLockedExchange(g_DataDelivered, 0) = 1 then // abfragen ob daten da sind
    begin
    UpdateForm; // update Form schreibt die daten in ein listview
    SetEvent(EventRequestSubmitted); // das event, daß den thread dazu bewegen soll daten abzurufen
    end;
end;
Ich hoffe das hilft dir - ich hab ziemlich lange gebraucht, daß alles hinzubekommen - naja ich hab damit auch angefangen mit Delphi zu programmieren

Arnulf
  Mit Zitat antworten Zitat
Benutzerbild von Airblader
Airblader

Registriert seit: 29. Okt 2004
Ort: Geislingen an der Steige
742 Beiträge
 
#3

Re: UDP -> Vom Server Daten lesen

  Alt 7. Sep 2005, 23:35
Hi,
Sorry dass ich so spät komme

Erstmal ein Riesendanke
Werd mir das alles nun durchlesen

Und ja, es geht um GameServer

air

Edit: Dass deine (1.) Methode geht, ist aber sicher? Ich bekomme nie eine Antwort vom Server, wobei es natürlich mit dem Server zu tun haben kann.
Ingo Bürk
Es nimmt der Augenblick, was Jahre geben.

Johann Wolfgang von Goethe
  Mit Zitat antworten Zitat
Arnulf

Registriert seit: 28. Okt 2004
Ort: Wien
271 Beiträge
 
#4

Re: UDP -> Vom Server Daten lesen

  Alt 8. Sep 2005, 11:31
Ich werd die methode mit dem thread nochmal umschreiben.
Ich möchte das eher event basierend aufbauen.
Aber im prinzip funktioniert es so.
Keine Ahnung wann ich dazu zeit hab - aber ich denk es geht besser.

Arnulf
  Mit Zitat antworten Zitat
Arnulf

Registriert seit: 28. Okt 2004
Ort: Wien
271 Beiträge
 
#5

Re: UDP -> Vom Server Daten lesen

  Alt 11. Sep 2005, 18:12
zu deinem edit
ja die methode geht sogar sehr sicher.
Das war die erste praktikable Lösung die ich hatte für udp.

das ganze rundherum ist ja nur in eine funktion verpackt.
und ich hab hald einen try counter also ich probier es 3 mal um sicher zu gehen, daß ich auch antwort bekomme.

Die funktion funktioniert sogar sehr gut - ich denk mal dein problem wird am gameserver scheitern.
Gameserver reagieren nämlich nicht auf falsche befehle - du mußt also genau wissen welches spiel das ist und welches commando do schicken mußt.

Im fall eine quake III engine oder eben medal of honor ist es hald:
"#255#255#255#255#2rcon rconpassword status" um einen status befehl zu schicken.
ohne rconpassword kann man ja nur getstatus ( wieviele user spielen gerade oder so ) abrufen:
"#255#255#255#255#2 status"

Arnulf
  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 07:01 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz