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 = '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;
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