![]() |
UDP -> Vom Server Daten lesen
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 ![]() um den Text zu lesen:
Delphi-Quellcode:
Also im Receiveevent.
procedure ...
var RecBuf: string; begin UdpSocket1.ReceiveBuf(RecBuf, UdpSocket1.BytesReceived); Form1.Memo1.Lines.Add(RecBuf); end; 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; |
Re: UDP -> Vom Server Daten lesen
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:
Wichtig zu wissen ist wohl was ActiveSleep macht:
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;
Delphi-Quellcode:
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).
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; 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:
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:
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 = 'next' then 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;
Delphi-Quellcode:
Ich hoffe das hilft dir - ich hab ziemlich lange gebraucht, daß alles hinzubekommen - naja ich hab damit auch angefangen mit Delphi zu programmieren :)
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; Arnulf |
Re: UDP -> Vom Server Daten lesen
Hi,
Sorry dass ich so spät komme :) Erstmal ein Riesendanke :thumb: 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. |
Re: UDP -> Vom Server Daten lesen
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 |
Re: UDP -> Vom Server Daten lesen
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 |
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:20 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