Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi TCPServer Client daten verarbeiten (https://www.delphipraxis.net/146805-tcpserver-client-daten-verarbeiten.html)

danu1104 27. Jan 2010 08:24


TCPServer Client daten verarbeiten
 
Hallo es geht um einen Client der anscheintnach Binary code zum Server sendet bzw Bytes / Buffer


Ich möchte diese Bytes / Buffers verarbeiten aber wie fange ich an? Also im Readln ist nix womit ich dem client eine Antwort schicken könnte.


Ich arbeite schon länger mit delphi habe mich jedoch in dem Sinne noch nie beschäftigt :D

Ich wär sehr dankbar über Antworten :)

Edit:

Delphi-Quellcode:
 
z
·



:
¸
=
«


$
°


k
¥
A
È
das kommt raus wenn ich das

Delphi-Quellcode:
if AContext.Connection.Connected then
begin
   memo1.Lines.Add(AContext.Connection.IOHandler.ReadString(1));
end;
mache

Astat 27. Jan 2010 09:19

Re: TCPServer Client daten verarbeiten
 
Hallo danu1104, bist Du Server und oder Client?
Was verstehst Du unter, "Daten weiterverarbeiten"?
Hast Du schon Code?

Beschreib das alles bitte mal genauer, mann kennt sich da nicht recht aus, was Du eigentlich willst.

lg. Astat

danu1104 27. Jan 2010 09:48

Re: TCPServer Client daten verarbeiten
 
Ich bin der Server und will von einem Client den ich natürlich nicht geschrieben habe die Login commands wissen (ich will nix hacken oder beschädigen)

bisher habe ich nur das was ich angegeben habe versucht weil ich ja auch schon mit indy arbeite, ging ich davon aus mit

ReadLn alle information zu erhalten:

ausschnit aus einem programm von mir:

Delphi-Quellcode:
 
comline:=TSTringlist.Create;
comline.Delimiter:=';';

comline.DelimitedText:=AThread.Connection.IOHandler.ReadLn();

if (comline.Strings[0] = '@KILLLOGIN') then
   begin
     Items.Caption:= '« Command '+comline.Strings[0]+' incoming ...';
     if KillProcess(ExtractFilename(Login_BIN)) then
     begin
       AThread.Connection.IOHandler.WriteLn('CLOSED')
      end else
      begin
       AThread.Connection.IOHandler.WriteLn('FAIL')
     end;
   end;
so ungefair, aber anscheint arbeitet dieser mit bytes und buffer das heisst
ich bin einwenig überfordert und habe paar fragezeichen aufn kopf ^^ :D

Meine frage, wie verarbeitet man bytes oder buffer, bzw wie finde ich raus um welchen typ stream es sich hier handelt.

ich kann ja mit der o.g. ausgabe nicht wirklich was anfangen , kann man es irgendwie decodieren?

Edit:
Es wär sehr hilfreich da ich ein eigenes MMOG an bastel bin und schwierigkeiten mit dem World Server habe als der der es möglich macht das 2 Player sich gegenüberstehen können, nur hatte ich bis jetzt das problem gehabt das beim schreiben der coordinaten in der Database entweder exception error kam oder das spiel eingefrohren ist. Und um das Problem zu lösen wollte ich mal schaun wie andere es gemacht haben ohne illegale action wie zb source decomplieren

ich habe einen Session/ Messanger und hier den world:

Delphi-Quellcode:
program MounttaSrv;

{$APPTYPE CONSOLE}

uses
  Forms,
  SysUtils,
  IdBaseComponent,
  IdComponent,
  IdTCPServer,
  idcontext,
  IdAntiFreezeBase,
  IdAntiFreeze,
  inifiles,
  Variants,
  Classes,
  keyboard;

type TServer = class(TIdTCPServer)
    Procedure ExecuteSettings;
    procedure DBServerConnect(AContext : TIDContext);
    procedure DBServerDisconnect(AContext : TIDContext);
    procedure DBServerExecute( AContext: TIdContext);
    Function RunCommand(cmd,dir:string):string;
  private
      IfEnd :Boolean ;
      Clients:Integer;
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;


var DBServer:TServer;
    INI:TIniFile;
    InCom2,Sett:TStringlist;

Procedure TServer.ExecuteSettings;
Var I:Integer;
    T:TextFile;
    S:TStringList;
begin
Sett:=TStringlist.Create;
S:=Tstringlist.Create;
S.LoadFromFile(ExtractFilePath(Paramstr(0))+'config.ini');

sett.Delimiter:=',';
Sett.DelimitedText:=s.Text;

for i := 0 to Sett.Count -1 do
begin

if Sett.Strings[i] = 'Mountara_Port' then
  begin
    DBServer.DefaultPort:=StrToInt(Sett.Strings[i+1]);
  end;

if Sett.Strings[i] = 'Mountara_ListenQueue' then
  begin
    DBServer.ListenQueue:=StrToInt(Sett.Strings[i+1]);
  end;

if Sett.Strings[i] = 'Mountara_Max_Connections' then
  begin
    DBServer.MaxConnections:=StrToInt(Sett.Strings[i+1]);
  end;

end;

end;

procedure TServer.DBServerDisconnect(AContext : TIDContext);
begin
  DBserver.Clients:=DBserver.Clients-1;
  WriteLn('» A User is Disconnected. ID ( ',AContext.Connection.Greeting.ID,' )');
  WriteLn('»» Clients Online: ',DBserver.Clients)
end;

procedure TServer.DBServerConnect(AContext : TIDContext);
begin
  DBserver.Clients:=DBserver.Clients+1;
  WriteLn('» A User is Connected. ID ( ',AContext.Connection.Greeting.ID,' )');
  WriteLn('»» Clients Online: ',DBserver.Clients)
end;

Function TServer.RunCommand(cmd,dir:string):string;
Var
 Ini:Tinifile;
 Op,Cm:TStringlist;
begin

 Op:=TStringlist.Create;
 Op.Delimiter:=' ';
 Op.DelimitedText:=CMD;

if Op.Strings[0] = 'GET' then
 begin
 Op.Delimiter:=':';
 Op.DelimitedText:=CMD;
 Ini:=Tinifile.Create(ExtractFilePath(Paramstr(0))+dir+'\'+Op.Strings[1]+'.mdb');
 Cm:=TStringlist.Create;
 Cm.Delimiter:=':';
 Cm.DelimitedText:=Op.Text;
 if not ini.SectionExists(Op.Strings[1])
  then begin

   WriteLn('» Datenbank Error:'+#13+'Eintrag konnte nicht gefunden werden! Setzen Sie den eintrag mit dem "SET" befehl.') ;
   WriteLn('»»');
 end else
   result:=ini.ReadString(Op.Strings[1],Cm.Strings[2],'');
 end else
if Op.Strings[0] = 'SET' then
begin
 Op.Delimiter:=':';
 Op.DelimitedText:=CMD;
 Ini:=Tinifile.Create(ExtractFilePath(Paramstr(0))+dir+'\'+Op.Strings[1]+'.mdb');
 Cm:=TStringlist.Create;
 Cm.Delimiter:=':';
 Cm.DelimitedText:=Op.Text;
try
if Cm.Count < 4 then
 begin
  WriteLn('» Datenbank Error:'+#13+'Kein oder Falsch angegebener wert.') ;
  WriteLn('»»');
  Exit;
  end else
  ini.WriteString(Op.Strings[1],Cm.Strings[2],Cm.Strings[3]);
  finally

    WriteLn('» Datenbank: eintrag '+ Cm.Strings[2]+' '+Cm.Strings[3]+' in '+Cm.Strings[1]+' war erfolgreich.');

    WriteLn('»»');
  end;
 end else
  begin

    WriteLn('» Datenbank Error:'+#13+'Solchein befehl ist mir nicht bekannt.');

    WriteLn('»»');
   end;
  ini.free;
end;

procedure TServer.DBServerExecute( AContext: TIdContext);
Var S,Player:String;
    Val:Integer;
    sVal:String;
begin
if AContext.Connection.Connected then
begin

   InCom2.DelimitedText:=AContext.Connection.IOHandler.ReadLn();
 // START
                            //  AContext.Connection.Socket.
   Player:=IntToStr(AContext.Connection.Greeting.Index);
   s:='SET ONLINEUSER:ENTRYS:1';
   RunCommand(S,'share\users');


 If InCom2.Strings[0] = 'GETENTRYS' then
 begin
   AContext.Connection.IOHandler.WriteLn('OnlinePlayers,'+Player);
 end else
 If InCom2.Strings[0] = 'GETPOSX' then
  begin
   S:='GET ONLINEUSER:POSX'+InCom2.Strings[1];
   sval:=RunCommand(S,'share\users');
   AContext.Connection.IOHandler.WriteLn('POSX,'+sval);
  end else
 If InCom2.Strings[0] = 'GETPOSY' then
  begin
   S:='GET ONLINEUSER:POSY'+InCom2.Strings[1];
   sval:=RunCommand(S,'share\users');
   AContext.Connection.IOHandler.WriteLn('POSY,'+sval);
  end else
 If InCom2.Strings[0] = 'GETPOSZ' then
  begin
   S:='GET ONLINEUSER:POSZ'+InCom2.Strings[1];
   sval:=RunCommand(S,'share\users');
   AContext.Connection.IOHandler.WriteLn('POSZ,'+sval);
  end;
   If InCom2.Strings[0] = 'SETPOSX' then
  begin
   S:='SET ONLINEUSER:POSX1:'+InCom2.Strings[1];
   sval:=RunCommand(S,'share\users');
  end;
     If InCom2.Strings[0] = 'SETPOSY' then
  begin
   S:='SET ONLINEUSER:POSY1:'+InCom2.Strings[1];
   sval:=RunCommand(S,'share\users');
  end;
     If InCom2.Strings[0] = 'SETPOSZ' then
  begin
   S:='SET ONLINEUSER:POSZ1:'+InCom2.Strings[1];
   sval:=RunCommand(S,'share\users');
  end;
  END;
end;

Procedure CreateServ;
Var i:Integer;
begin

WriteLn('»» ----------------------------------------------------------------');
WriteLn('»»','               PSDsoft Productions: 2007 - 2009.            ');
WriteLn('»» ----------------------------------------------------------------');
WriteLn('»»');
WriteLn('»» ',Application.Title);
WriteLn('»»');

 InCom2:=TStringlist.Create;
 DBServer:=TServer.Create(nil);

 DBServer.OnExecute:=DBServer.DBServerExecute;
 DBServer.OnDisconnect:=DBServer.DBServerDisconnect;
 DBServer.OnConnect:=DBServer.DBServerConnect;
 DBserver.Clients:=0;
 InCom2.Delimiter:=',';
try
 DBServer.ExecuteSettings;
except
  WriteLn('»» Error: Config - File is Missing.');
  Exit;
end;
  WriteLn('»» Set Server Port: ',IntToStr(DBServer.DefaultPort));

  Sleep(20);
 try
    DBServer.Active:=true;
  Sleep(20);
  finally
   if DBServer.Active then

    WriteLn('»» Set Server Start ....');
    WriteLn('»»');
    WriteLn('»» Clients: ',DBserver.Clients);
  end;
end;

var Key:String;
begin
Application.Title:='Mounttara World Server';

try
  try
   CreateServ;
  finally
   key:=keyboard.VirtualKeyCodeToKeyName(keyboard.KeyPressed());

 repeat
     ReadLn;
   until not true end;
  except
    on E:Exception do
      Writeln(E.Classname, ': ', E.Message);
  end;

end.
der nicht wirklich will

Astat 27. Jan 2010 10:51

Re: TCPServer Client daten verarbeiten
 
Zitat:

Zitat von danu1104
Meine frage, wie verarbeitet man bytes oder buffer, bzw wie finde ich raus um welchen typ stream es sich hier handelt.

Hallo danu1104, verwende ReadBuffer oder ReadStream, wie das bei den Indys genau heisst musst Du nachschlagen.

Wenn Du nun den Buffer gefüllt hast, ziehst Du rückschlüsse auf das Protokoll.

z.B. im Buffer sind 19 Byte, wir nehmen mal willkürlich ein Protokoll an, dass wie folgt aufgebaut ist.

4 Byte Länge der Daten + 4 Byte MsgID = 8 Byte, verbleiben 11 Byte.

Jetzt überprüfen wir ob diese Annahme stimmt?

Wir kopieren die ersten 4 Byte aus dem Buffer in eine integer Variable (iLen).
Delphi-Quellcode:
move(Buffer^, iLen, SizeOf(Integer));
Wenn der Wert der integer Variable nun 11 Byte anzeigt, haben wir den Header geknackt.
Dann werden die nächsten 4 Byte kopiert, und wir sehen die ID oder sonst ein Integer Logon Commando etc.?

Wenn der ermittelte Wert unserer integer Variable(n) undefinierte Werte liefert, müssen wir noch ein Byteshifting aller
Networkorder durchführen.
Delphi-Quellcode:
iLen := ntohl(DataRec.cbData);
Der Header kann auch geringfügig anderst aufgebaut sein, hier heisst es einfach durchprobieren.

lg. Astat

danu1104 27. Jan 2010 10:57

Re: TCPServer Client daten verarbeiten
 
Hört sich gut an was mache ich aber damit genau jetzt?

alles was ich momentan habe ist das:


Delphi-Quellcode:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
if AContext.Connection.Connected then
begin

    memo1.Lines.Add(AContext.Connection.IOHandler.ReadString(1));

  end;
end;
ich wär jetzt so naiv und würde wahrscheinlich alles falsch machn und so würde es dan aussehen

Delphi-Quellcode:
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
if AContext.Connection.Connected then
begin

    move(Buffer^, iLen, SizeOf(Integer));

  end;
end;
dann würde ich wohl fragen was falsch ist, ich entschuldige mich für mein bissen wissen was ich habe und hoffe doch das du mir da helfen kannst, ich finde es auf jedenfall toll das du bereit bist mir zu helfen. klasse! :thumb:


Edit: Habe folgende optionen mit indy:

http://www.psdpro.de/delphi.png (screenshot)

Astat 27. Jan 2010 11:56

Re: TCPServer Client daten verarbeiten
 
Zitat:

Zitat von danu1104
Habe folgende optionen mit indy:

Versuch mal read integer, da ist anscheinend die NetworkToHostByteOrder auch schon implementiert.

Noch ein Tip: Folgende Variablen sind nicht THreadsave, daher kommen auch Deine Probleme mit dem Server wenn
mehr als ein Client gleichzeitig connected sind.

Delphi-Quellcode:
    INI:TIniFile;
    InCom2,Sett:TStringlist;

lg. Astat


Alle Zeitangaben in WEZ +1. Es ist jetzt 17:41 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