Delphi-PRAXiS
Seite 1 von 2  1 2      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy TCP Problem. (https://www.delphipraxis.net/131431-indy-tcp-problem.html)

danu1104 24. Mär 2009 23:08


Indy TCP Problem.
 
Hallo,


Ich habe mit Indy 9 (ob es richtig ist ka) die "Player" also Listener abgefragt
Delphi-Quellcode:

try
   Player:=IntToS(AThread.Connection.Server.MaxConnectionReply.Index);
   s:='SET ONLINEUSER:ENTRYS:'+Player+'';
   RunCommand(S);
 except
  exit;
 end;
 finally
 If InCom2.Strings[0] = 'GETENTRYS' then
 begin
   AThread.Connection.WriteLn('OnlinePlayers,'+Player);
   { Danach erstellt der CLient zur laufzeit Actor[Player]
    und und fängt an diese zu Positionieren }
 end;
 If InCom2.Strings[0] = 'GETPOSX' then
  begin
   S:='GET POSX'+InCom2.Strings[1];
   sval:=RunCommand(S);
   AThread.Connection.WriteLn('POSX,'+sval);
  end;

usw...
damit der Server die informationen von jedem
eizelnen Spieler zum client senden kann. Damit die Spieler sichbar werden können.

Und um es dynamisch zu halten habe ich es in der art einer Playlist gemacht, so das 1 Mil Player drauf können also Ohne einschränkungen

Delphi-Quellcode:

[ONLINUSER]
ENTRYS=2

posx1=20
posy1=133
posz1=-0

posx2=20
posy2=133
posz2=-0
Das funktioniert auch alles wunderbar, aber da Indy 9 (bei 10 weiss ich es nochnet) immer Probleme macht von Wegen mit der Meldung "Verbindung wurde erfolgreich geschlossen" obwohl es garnicht verordnet wurde, und ich einen Timmer mit 100ms habe, der dauernt nach playern fragt, pos... usw, könnt ihr euch sicher vorstellen was das für ein Spam ist wenn indy anfäng zu buggen.

Deshalb habe ich Indy 10 Installiert, ... alles schön und gut aber wie frage ich den Bei Indy 10, wieviel "Spieler" zu dem Server verbunden sind?? Ich habe echt kein plan.

Ich freue mich auf jeder antwort!! Love Ya All :P

Danu.

nuclearping 25. Mär 2009 08:06

Re: Indy TCP Problem.
 
Wenn ich recht entsinne so:
Delphi-Quellcode:
var
  cList: TList;
  Count: Integer;
begin
  cList := IdTCPServer.Contexts.LockList;
  try
    for Count := 0 to cList.Count -1 do
      with TIdContext(cList[Count]) do
        Connection.IOHandler.WriteLn ('...');
  finally
    IdTCPServer.Contexts.UnlockList;
  end;
end;

danu1104 25. Mär 2009 08:24

Re: Indy TCP Problem.
 
Okay, ich werds Probieren, kann mir evtl jemand auch sagen warum ich immer diese meldung habe sobald ich was zum server schicke etc ... also die Meldung "Verbindung erfolgreich geschlossen" ... Mich nervt das einwenig.. ich würde ja aufgrund desen lieber versuchen Winsocks zu nutzen aber der gibt Fehlercodes raus womit keiner was anfangen kann ( ich zumindest ). SInd das chikanen oder habe ich einfach nur was falsch gemacht? Also Ich habe aner Komponente nix weiteres ausser Port angaben geändert, brauche ich evtl einen ThreadMgr oder sonstiges um den server ohne ewigen Spam laufen zu lassen

Ich sag mal ist ja nicht gerade toll wenn man ewig schilder weg drückt nur weil indy meint ewig die verbindung zu trennen, vorallem kommt das sehr böse wenn es sich dann noch um ein Spiel handelt.


Ich lege einfach mal den Server - OnExecute code bei:

Delphi-Quellcode:
procedure TForm1.DBServerExecute(AContext: TIdContext);
Var S:String;
    Val:Integer;
    sVal:String;
begin
if BusyGRP.ItemIndex = 0 then Exit;
if AContext.Connection.Connected then
begin
try
   InCom.DelimitedText:=AContext.Connection.IOHandler.ReadLn();
  finally
if InCom.Strings[0] = 'GETEXP' then
 begin
   sval:=RunCommand('GET '+InCom.Strings[1]+':'+'gexp');
   AContext.Connection.IOHandler.WriteLn('GEXP'+','+sVal);
  end;
if InCom.Strings[0] = 'GETPWD' then
 begin
   sval:=RunCommand('GET '+InCom.Strings[1]+':'+'Password');
   AContext.Connection.IOHandler.WriteLn('PWD'+','+sVal);
  end;
if InCom.Strings[0] = 'GETHEAL' then
 begin
   val:=StrToInt(RunCommand('GET '+InCom.Strings[1]+':'+'aheal'));
   AContext.Connection.IOHandler.WriteLn('HEAL'+','+IntToStr(Val));
  end;
if InCom.Strings[0] = 'GETAPNTS' then
 begin
   val:=StrToInt(RunCommand('GET '+InCom.Strings[1]+':'+'apnts'));
   AContext.Connection.IOHandler.WriteLn('APNTS'+','+IntToStr(Val));
  end;
if InCom.Strings[0] = 'GETSTR' then
 begin
   val:=StrToInt(RunCommand('GET '+InCom.Strings[1]+':'+'astr'));
   AContext.Connection.IOHandler.WriteLn('STR'+','+IntToStr(Val));
  end;
 if InCom.Strings[0] = 'SETAPNTS' then
   begin
    S:='SET '+InCom.Strings[1]+':'+'apnts'+':'+InCom.Strings[2];
    usrlog.SelAttributes.Color:=clblue;
    usrlog.SelText:=''+'»»'+' ';
    usrlog.SelAttributes.Color:=clred;
    usrlog.SelText:=''+InCom.Strings[1]+' ';
    usrlog.SelText:=''+' hat '+InCom.Strings[2]+' apnts.'+slinebreak;
    try
     RunCommand(S);
    except
     usrlog.SelAttributes.Color:=clred;
     usrlog.SelAttributes.Style:=[];
     usrlog.SelText:=''+'»»'+' ';
     usrlog.SelAttributes.Color:=clblue;
     usrlog.SelText:=''+' Fehlgeschlagen.'+''+slineBreak;
    end;
   end else
  if InCom.Strings[0] = 'SETSTR' then
   begin
    S:='SET '+InCom.Strings[1]+':'+'astr'+':'+InCom.Strings[2];
    usrlog.SelAttributes.Color:=clblue;
    usrlog.SelText:=''+'»»'+' ';
    usrlog.SelAttributes.Color:=clred;
    usrlog.SelText:=''+InCom.Strings[1]+'';
    usrlog.SelText:=''+' hat jetzt '+InCom.Strings[2]+' STR.'+slinebreak;
    try
     RunCommand(S);
    except
     usrlog.SelAttributes.Color:=clred;
     usrlog.SelAttributes.Style:=[];
     usrlog.SelText:=''+'»'+' ';
     usrlog.SelAttributes.Color:=clblue;
     usrlog.SelText:=''+' Fehlgeschlagen.'+''+slineBreak;
    end;
   end else
  if InCom.Strings[0] = 'SETHEAL' then
   begin
    S:='SET '+InCom.Strings[1]+':'+'aheal'+':'+InCom.Strings[2];
    usrlog.SelAttributes.Color:=clblue;
    usrlog.SelText:=''+'»'+' ';
    usrlog.SelAttributes.Color:=clred;
    usrlog.SelText:=''+InCom.Strings[1]+'';
    usrlog.SelText:=''+' hat jetzt '+InCom.Strings[2]+' Heal.'+slinebreak;
   try
     RunCommand(S);
    except
     usrlog.SelAttributes.Color:=clred;
     usrlog.SelAttributes.Style:=[];
     usrlog.SelText:=''+'»»'+' ';
     usrlog.SelAttributes.Color:=clblue;
     usrlog.SelText:=''+' Fehlgeschlagen.'+''+slineBreak;
    end;
   end else
  if InCom.Strings[0] = 'SETDEF' then
   begin
    S:='SET '+InCom.Strings[1]+':'+'def'+':'+InCom.Strings[2];
    usrlog.SelAttributes.Color:=clblue;
    usrlog.SelText:=''+'»»'+' ';
    usrlog.SelAttributes.Color:=clred;
    usrlog.SelText:=''+InCom.Strings[1]+'';
    usrlog.SelText:=''+' hat jetzt '+InCom.Strings[2]+' Def.'+slinebreak;
   try
     RunCommand(S);
    except
    usrlog.SelAttributes.Color:=clred;
     usrlog.SelAttributes.Style:=[];
     usrlog.SelText:=''+'»»'+' ';
     usrlog.SelAttributes.Color:=clblue;
     usrlog.SelText:=''+' Fehlgeschlagen.'+''+slineBreak;
    end;
   end else
  end;
  if InCom.Strings[0] = 'SETDMG' then
   begin
    S:='SET '+InCom.Strings[1]+':'+'dmg'+':'+InCom.Strings[2];
    usrlog.SelAttributes.Color:=clblue;
    usrlog.SelText:=''+'»»'+' ';
    usrlog.SelAttributes.Color:=clred;
    usrlog.SelText:=''+InCom.Strings[1]+'';
    usrlog.SelText:=''+' macht jetzt '+InCom.Strings[2]+' Dmg.'+slinebreak;
   try
     RunCommand(S);
    except
     usrlog.SelAttributes.Color:=clred;
     usrlog.SelAttributes.Style:=[];
     usrlog.SelText:=''+'»»'+' ';
     usrlog.SelAttributes.Color:=clblue;
     usrlog.SelText:=''+' Fehlgeschlagen.'+''+slineBreak;
    end;
   end else
 if InCom.Strings[0] = 'SETEXP' then
   begin
    S:='SET '+InCom.Strings[1]+':'+'gexp'+':'+InCom.Strings[2];
    usrlog.SelAttributes.Color:=clblue;
    usrlog.SelText:=''+'»»'+' ';
    usrlog.SelAttributes.Color:=clred;
    usrlog.SelText:=''+InCom.Strings[1]+'';
    usrlog.SelText:=''+' hat jetzt '+InCom.Strings[2]+' Exp von ???.'+slinebreak;
   try
     RunCommand(S);
    except
     usrlog.SelAttributes.Color:=clred;
     usrlog.SelAttributes.Style:=[];
     usrlog.SelText:=''+'»»'+' ';
     usrlog.SelAttributes.Color:=clblue;
     usrlog.SelText:=''+' Fehlgeschlagen.'+''+slineBreak;
    end;
   end else
 end;
end;
und hier die Client Source zur übertragung von Infos:

Delphi-Quellcode:
Function GetInfo(Typ:String):Integer;
Var SRV:TStringlist;
begin
Form1.DBCLient.Address:='localhost';
 If not Form1.DBCLient.Active then Form1.DBCLIENT.Active:=true;
 SRV:=Tstringlist.Create;
 SRV.Delimiter:=',';
  try
   Form1.DBClient.Socket.SendText('GET'+Typ+','+Form1.Username);
  finally
    Srv.DelimitedText:=Form1.DBClient.Socket.ReceiveText();
   if Srv.Strings[0] = TYP then
    Result:=StrToInt(Srv.Strings[1]);
  end;
end;

Function GetInfoS(Typ:String):String;
Var SRV:TStringlist;
begin
Form1.DBCLient.Address:='localhost';
 If not Form1.DBCLient.Active then Form1.DBCLIENT.Active:=true;
 SRV:=Tstringlist.Create;
 SRV.Delimiter:=',';
  try
   Form1.DBClient.Socket.SendText('GET'+Typ+','+Form1.Username);
  finally
    Srv.DelimitedText:=Form1.DBClient.Socket.ReceiveText;
   if Srv.Strings[0] = TYP then
    Result:=Srv.Strings[1];
  end;
end;

Procedure ModifyInfo(Typ:String;Points:Integer); overload;
begin
Form1.DBCLient.Address:='localhost';
  If not Form1.DBCLient.Active then Form1.DBCLIENT.Active:=true;
  Form1.DBClient.Socket.SendText('SET'+TYP+','+Form1.Username+','+IntToStr(Points));
end;

Procedure ModifyInfo(Typ:String; Str:String); overload;
begin
Form1.DBCLient.Address:='localhost';
 If not Form1.DBCLient.Active then Form1.DBCLIENT.Active:=true;
  Form1.DBClient.Socket.SendText('SET'+TYP+','+Form1.Username+','+Str);
end;
Edit: ähm ja, ich habe überall in den abfragen das ELSE vergessen, ob das jetzt der grund ist idknow, aber ich kanns mir net vorstellen da Indy sogar bei meinen Messanger Projekt son terz gemacht hat und daher ...

RunCommand(); ist nichts besonderes, mit der Function Simuliere ich nur eine DB im format einer INI datei, SET DATEI&SECTION:IDENT:VALUE (Werte schreiben / setzen) GET DATEI&SECTION:IDENT ...auslesen

nuclearping 25. Mär 2009 08:39

Re: Indy TCP Problem.
 
Die Exception kommt nur in der IDE. Und die kannst du über die Exceptions-Einstellungen ignorieren lassen.

danu1104 25. Mär 2009 08:41

Re: Indy TCP Problem.
 
Woot? Ich habe auf meinen Test Rechner keine IDE's, die meldung kommt mit oder ohne Debugger.

nuclearping 25. Mär 2009 08:43

Re: Indy TCP Problem.
 
"Woot" = "We Own Opposing Team" ;)

Und zur Execption: Ist mir neu. Kenne das nur, dass die in der IDE kommt ... :gruebel:

danu1104 25. Mär 2009 08:55

Re: Indy TCP Problem.
 
Wie soll ich den eine meldung ignorieren wenn genau das der fall ist.

Stellt euchmal GuildWars, 2Moons oder sontiges MMOG vor okay? So Stats setzen geht nur (!) wenn eine verbindung steht
also alles wird in meiner Proviesorischen DB gespeichert. Wenn keine verbindung besteht kannste drücken bis der arzt kommt die werte werden nicht verändert.

siehe hier:
Delphi-Quellcode:
 
procedure TForm1.PlusStrButtonClick(Sender: TObject);
Var SRvVal,SrvSP,Value,Pnt:Integer;
begin
if StrToint(MUSPnt.Caption) < 1 then Exit;
SRvVal:=GetInfo('STR');
Value:=SRvVal+1;
try
 ModiFyInfo('STR',Value);
finally
ATSTR.Caption:=IntToStr(GetInfo('STR'));
SRvSP:=GetInfo('APNTS');
Pnt:= SRvSP -1;
try
  ModiFyInfo('APNTS',Pnt);
 finally
  MUSPnt.Caption:=IntToStr(GetInfo('APNTS'));
 end;
end;

globerg:=GetInfo('STR')*6;
globatk:=GetInfo('STR')*7;
globdmg:=RandomRange(globerg,globatk)-globdef;
ATKRATE.Caption:='Attack Rate: '+slinebreak+' '+IntToStr(GetInfo('STR')*6)+' ~ '+IntToStr(GetInfo('STR')*7)
end;
Durch die ewigen Disconnect von indy werden die Punkte asyncron inkl der tollen schielder. Was ich wissen will ist, wie kann ich dafür sorgen das nicht ewig die verbindungen vom clienten zum server getrennt werden.


Client

nuclearping 25. Mär 2009 09:13

Re: Indy TCP Problem.
 
In meinem letzten Projekt hab ich Indy10 verwendet und kann das Problem, was du da schilderst, nicht nachvollziehen.

Ich weiß, dass dir das jetzt auch nicht viel hilft. Aber vielleicht bringts dich auf eine Spur, wo da der Wurm drin sein könnte. :mrgreen:

Mach doch vielleicht mal ein leeres Projekt, wo du einfach nur 'ne grundlegende TCP-Verbindung und -Kommunikation umsetzt und versuche da, den Knoten aufzudröseln. :gruebel:

DataCool 29. Mär 2009 23:47

Re: Indy TCP Problem.
 
Hi,

also ich nutze Indy 9 und 10 in einigen Projekten und habe Deine Meldung nicht nie bekommen,
hilft Dir zwar nicht weiter aber das schonmal vorab als Info.

Es liegt nicht an Indy sondern irgentwo in Deinem Code bzw. am Aufbau !

In Deinem Client-Code hast Du mehrere Function die dem Server etwas Senden und auf Antwort warten:
- GetInfo, GetInfoS, etc.
Werden ^^ diese ^^ nur von Deinem Button Click aufgerufen ?
Oder vielleicht sogar noch von einem Timer oder Thread aus ?
Ich vermute jetzt nämlich mal ins Blaue das sich die einzelnen functions asyncron in die Quere kommen.

zum Server-Code:
- Was macht Deinen Server Code(OnExecute), wenn beim ReadLn keine Antwort(TimeOut) erhält ?
- Dein UserLog ist eine VCL-Komponente, diese ist NICHT THREAD-SAFE, alle Zugriffe muss syncronisiert geschehen
- Dein RunCommand, nutzt eine Ini als Mini-DB ? Also wird in eine Datei geschrieben auch dieses IST NICHT THREAD SAFE

Du siehst also es gibt mehrere Stellen die Dein Problem verursachen könnten.

Greetz Data

danu1104 31. Mär 2009 05:08

Re: Indy TCP Problem.
 
Ich habe 3 CLients und 3 Server, on timer event gibt es nur einen Coordinaten austauch und chat messages zu entfangen, aber beide haben erschiedene Server. Es gibt einen DB Server der nur informationen speichert das heisst Stats , Exp, Name, Login. Der message Server Empfängt messages und leitet sie global weiter, so das sie jeder lesen kann, das konnte ich fixen. bei stats verteillung Liest und Schreibt er gleichzeitig.

Aber deine ahnung trifft zu, bei einen Klick des STR Buttons Werden mehrere informationen Gesendet und angefordert

Delphi-Quellcode:

procedure TForm1.PlusStrButtonClick(Sender: TObject);
Var SRvVal,SrvSP,Value,Pnt:Integer;
begin
if StrToint(MUSPnt.Caption) < 1 then Exit;
SRvVal:=GetInfo('STR'); // Anfordern
Value:=SRvVal+1;
try
ModiFyInfo('STR',Value); // setzen
finally
ATSTR.Caption:=IntToStr(GetInfo('STR')); // Anfordern
SRvSP:=GetInfo('APNTS'); // Anfordern
Pnt:= SRvSP -1;
try
  ModiFyInfo('APNTS',Pnt);// setzen
finally
  MUSPnt.Caption:=IntToStr(GetInfo('APNTS')); // Anfordern
end;
end;

globerg:=GetInfo('STR')*6; // Anfordern
globatk:=GetInfo('STR')*7; // Anfordern
globdmg:=RandomRange(globerg,globatk)-globdef;
ATKRATE.Caption:='Attack Rate: '+slinebreak+' '+IntToStr(GetInfo('STR')*6)+' ~ '+IntToStr(GetInfo('STR')*7) // Anfordern
end;

Ich werde mal schaun ob ich das einwenig verringern kann.

Beim chat habe ich das "Einfrieren" rausbekommen, der client hat sich einfach imma aufgehangen nach absenden der message, und es lag an try ... abfrage.

Aber wie soll ich ein MMOG baun, wenn der Server nach "1" client schon überfordert ist ist konsolen anwendung dafür besser?


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:51 Uhr.
Seite 1 von 2  1 2      

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