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 Client/Server (https://www.delphipraxis.net/167447-indy-tcp-client-server.html)

BlackSeven 30. Mär 2012 07:40

Indy TCP Client/Server
 
Hallo,

ich schicke innerhalb einer Sekunde mehrere Datenpakete an einen TCP-Server.

Mein Problem:
Nach kurzer Zeit kommen auf dem Server keine Daten mehr an.

Gleiches Problem wie hier beschrieben:
http://stackoverflow.com/questions/9...nding-packages

Hat vielleicht jemand ein paar Ideen/Anregungen?

Danke.

Furtbichler 30. Mär 2012 07:49

AW: Indy TCP Client/Server
 
Zitat:

Zitat von BlackSeven (Beitrag 1159333)
Hat vielleicht jemand ein paar Ideen/Anregungen?

Erstelle ein Demo-Projekt, erkläre, was und wie Du die Daten schickst, und was und wie Du die Daten empfängst.

BlackSeven 30. Mär 2012 09:20

AW: Indy TCP Client/Server
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hier ein kleines Demo-Projekt, um das Ganze zu demonstrieren.

Versand:
Delphi-Quellcode:
 

var

  I   : Integer;
  Data : TBytes;

begin

  Send.Enabled := False;

  Application.ProcessMessages;

  for I := 1 to 10000 do
  begin

    SetLength(Data, SizeOf(Integer));

    Move(PByte(I), Data[0], SizeOf(Integer));

    FClient.IOHandler.Write(LongInt(Length(Data)));
    FClient.IOHandler.Write(Data);

  end;

end;
Empfang:
Delphi-Quellcode:
var

  DataSize : LongInt;
  Data    : TBytes;
  Value   : Integer;

begin

  if AContext.Connection.IOHandler.Readable then
  begin

    DataSize := AContext.Connection.IOHandler.ReadLongInt;
    AContext.Connection.IOHandler.ReadBytes(Data, DataSize);

    Value := 0;
    Move(Data[0], PByte(Value), SizeOf(Integer));

    TThread.Queue
    (

      TThread.CurrentThread,

      procedure
      begin

        UI.Caption := IntToStr(Value);

      end

    );

  end;

end;

mjustin 30. Mär 2012 09:31

AW: Indy TCP Client/Server
 
Zitat:

Zitat von BlackSeven (Beitrag 1159356)
Delphi-Quellcode:
 

    TThread.Queue
    (

      TThread.CurrentThread,

      procedure
      begin

        UI.Caption := IntToStr(Value);

      end

    );

Liegt es eventuell an diesem Teil? Werden alle Nachrichten empfangen, wenn man einfach nur einen Zähler erhöht?

sx2008 30. Mär 2012 09:58

AW: Indy TCP Client/Server
 
Dein Sender schickt immer 4 Byte Länge + Nutzdatenblock.
Der Empfänger muss folgende Strategie anwenden.
1.) empfangener Datenblock an den Empfangpuffer anfügen (anhängen)
Jede TCP/IP-Verbindung benötigt ihren eigenen Empfangspuffer
2.) Falls Länge Empfangspuffer < 4 nichts tun (Exit; )
3.) die ersten 4 Bytes aus Empfangspuffer als Längenfeld auslesen
4.) falls Länge Empfangspuffer < Längenfeld + 4 dann nichts tun (Exit; )
5.) Aus dem Empfangspuffer werden die 4 Bytes + der Nutzdatenblock ausgeschnitten
Der Nutzdatenblock wird über ein Event der weiteren Verarbeitung zugeführt
6.) Gehe zu 2.)

Nur so gelingt eine saubere Kommunikation!

mjustin 30. Mär 2012 10:42

AW: Indy TCP Client/Server
 
Zitat:

Zitat von sx2008 (Beitrag 1159366)
Dein Sender schickt immer 4 Byte Länge + Nutzdatenblock.
Der Empfänger muss folgende Strategie anwenden.
...
Nur so gelingt eine saubere Kommunikation!

Im Prinzip ja, aber der Indy TIdTCPServer kapselt den Low-level Teil dieses Vorgehens bereits. Man muss also nur noch das Protokoll (Länge lesen, dann Daten lesen) behandeln.

BlackSeven 30. Mär 2012 11:15

AW: Indy TCP Client/Server
 
Zitat:

Im Prinzip ja, aber der Indy TIdTCPServer kapselt den Low-level Teil dieses Vorgehens bereits

Ich kann die Befehle + Daten in eine threadsichere Queue packen und dann versenden.
Ändert das überhaupt was?
Delphi-Quellcode:
procedure Invoke(const ACommandID: Integer; const AData: TBytes);
begin

  Queue.Push(TCommand.Create(ACommandID, AData);
 
  EventSend.SetEvent;

end;
Im Thread, der für das Versenden zuständig ist:
Delphi-Quellcode:
procedure TSendThread.Execute;
var
 
  Command : TCommand;

begin

  WaitForSingleObject(EventSendHandle, INFINITE);

  Command := Queue.Pop;

  // Daten versenden

end;

BlackSeven 30. Mär 2012 13:48

AW: Indy TCP Client/Server
 
So funktioniert es:
Delphi-Quellcode:
var

  DataSize : LongInt;
  Data    : TBytes;
  Value   : Integer;

begin

  AContext.Connection.IOHandler.CheckForDataOnSource(10);

  if not AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin

    DataSize := AContext.Connection.IOHandler.ReadLongInt;
    AContext.Connection.IOHandler.ReadBytes(Data, DataSize);

    Value := 0;
    Move(Data[0], PByte(Value), SizeOf(Integer));

    TThread.Queue
    (

      TThread.CurrentThread,

      procedure
      begin

        UI.Caption := IntToStr(Value);

      end

    );

  end;

end;

Zitat:

AContext.Connection.IOHandler.CheckForDataOnSource (10);

shmia 30. Mär 2012 14:49

AW: Indy TCP Client/Server
 
Zitat:

Zitat von mjustin (Beitrag 1159391)
Im Prinzip ja, aber der Indy TIdTCPServer kapselt den Low-level Teil dieses Vorgehens bereits

Da habe ich meine Zweifel.
Angenommen es treffen 1500 frische Bytes beim Empfänger ein.
Dann wird folgender Code ausgeführt
Delphi-Quellcode:
  if not AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    // 4 Bytes auslesen
    DataSize := AContext.Connection.IOHandler.ReadLongInt;
    // Nutzdaten lesen  
    AContext.Connection.IOHandler.ReadBytes(Data, DataSize);
Was aber wenn Datasize=2000 aber es sind nur 1496 Bytes im Puffer?
Dann werden bei ReadBytes auch nur 1496 Bytes gelesen.
(Sollte man nicht den Rückgabewert von ReadBytes() auswerten?)
Alle folgende Datenpakete werden dann falsch interpretiert!!
Denn sobald die restlichen Daten eintreffen "denkt" der Empfänger er würde
wieder eine Längenangabe bekommen, in Wirklichkeit sind es aber 4 Byte aus der Mitte
eines Nutzdatenblocks.

mjustin 30. Mär 2012 15:31

AW: Indy TCP Client/Server
 
Zitat:

Zitat von shmia (Beitrag 1159446)
Was aber wenn Datasize=2000 aber es sind nur 1496 Bytes im Puffer?
Dann werden bei ReadBytes auch nur 1496 Bytes gelesen.

ReadBytes blockiert bis die gewünschte Anzahl Bytes gelesen wurde, oder ein TimeOut auftritt.

Delphi-Quellcode:
 procedure ReadBytes(var VBuffer: TIdBytes; AByteCount: Integer; AAppend: Boolean = True); virtual;
ist eine Prozedur, daher ist der Rückgabewert unproblematisch.

Aber der dritte Parameter ist verdächtig: wenn VBuffer bereits Daten enthält, werden neue Daten angehängt.

Nach ReadBytes sollten die Daten doch bereits in Data stehen, was macht dann diese Zeile?

Delphi-Quellcode:
 Move(Data[0], PByte(Value), SizeOf(Integer));


Alle Zeitangaben in WEZ +1. Es ist jetzt 21:45 Uhr.
Seite 1 von 2  1 2      

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