简体   繁体   中英

Indy TIdTCPServer TIdTCPClient data exchange

I spent some time to write a simple application to exchange data between TIdTCPServer and TIdTCPClient . But now I'm stuck.
I can send data from TIdTCPClient to TIdTCPServer and can process this.
But have no idea and official documentation didn't give any clue how to send data from TIdTCPServer and process it on TIdTCPClient . Please advise.

My code is simple:

main application:

var
  Form1: TForm1;

implementation

uses ClientThread, ServerThread;

var
  ClientThread: TClientThread;
  ServerThread: TServerThread;

{$R *.fmx}

procedure TForm1.Button1Click(Sender: TObject);
var OutputDebugString:string;
begin
  ServerThread:=TServerThread.Create(False);
  ServerThread.Priority:=tpNormal;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  ClientThread:=TClientThread.Create(False);
  ClientThread.Priority:=tpNormal;
 end;

Server Thread:

unit ServerThread;

interface

uses
  Classes, System.SysUtils, IdContext, IdTCPServer, TaskQue;

type
  TServerThread = class(TThread) //MyThread - заданное нами имя потока.
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

 TServer = class(TObject)
   IdTCPServer1: TIdTCPServer;
   procedure IdTCPServer1Execute(AContext: TIdContext);
   procedure IdTCPServer1Connect(AContext: TIdContext);
  private
   { Private declarations }
   constructor Create;
  public
  end;

type
TDatagram = record
    Proto: byte;
    Command: word;
    DataSize: word;
    data: array [0..4096] of byte;
  end;

var
  Server : TServer;

implementation

uses YouFreedom;

constructor TServer.Create;
begin
 inherited Create;
 IdTCPServer1 := TIdTCPServer.Create(nil);
 IdTCPServer1.Bindings.Clear;
// IdTCPServer1.DefaultPort := 10001;
  try
    with idTCPserver1.Bindings.Add do
    begin
      IP := '127.0.0.1';
      Port := 10001;
    end;
  finally     //dirty hack
      idTCPserver1.Bindings.Add.IP := '127.0.0.1';
      idTCPserver1.Bindings.Add.Port := 10002;
  end;
// idTCPserver1.Bindings.Add.Port:=10001;
// IdTCPServer1.Bindings.Add.IP := '127.0.0.1';
 IdTCPServer1.Tag := 0;
 IdTCPServer1.TerminateWaitTime := 5000;
 IdTCPServer1.OnConnect := IdTCPServer1Connect;
 IdTCPServer1.OnExecute := IdTCPServer1Execute;
end;

procedure TServer.IdTCPServer1Execute(AContext: TIdContext);

var
  MIRec: TDatagram;
  msRecInfo: TMemoryStream;
  size: integer;
  i:integer;
  recieve:byte;
  respstream: TMemoryStream;
begin
  try
   msRecInfo:= TMemoryStream.Create;
   AContext.Connection.IOHandler.ReadStream(msRecInfo, -1, false);
   msRecInfo.Position := 0;
   msRecInfo.ReadBuffer(MIRec, msRecInfo.size);
   Form1.addtoque := '1';
//   Form1.s := inttostr(MIRec.Proto)
  Form1.Memo1.Lines.Add('Proto = ' + inttostr(MIRec.Proto));
  finally
   msRecInfo.Free
  end;
end;

procedure TServer.IdTCPServer1Connect(AContext: TIdContext);
begin
//AContext.Connection.Socket.WriteLn('hello');
end;

procedure TServerThread.Execute;
begin
 Server := TServer.Create;
 try
  Server.IdTCPServer1.Active := True;
 except
      on E: Exception do
       // OutputDebugString(PChar(E.ToString)); //do something
      end;
end;


end.

Client thread:

unit ClientThread;

interface

uses
  Classes, IdTCPClient;

type
  TClientThread = class(TThread) //MyThread - заданное нами имя потока.
  private
    { Private declarations }
  protected
    procedure Execute; override;
  end;

 TClient = class(TObject)
   IdTCPClient1: TIdTCPClient;
//   procedure IdTCPClient1OnWorkBegin(AContext: TIdContext);
  private
   { Private declarations }
   constructor Create;
  public
  end;

implementation

type
TDatagram = record
    Proto: byte;
    Command: word;
    DataSize: word;
    data: array [0..4096] of byte;
  end;

var
  ClientConnection : TClient;

constructor TClient.Create;
begin
 inherited Create;
 IdTCPClient1 := TIdTCPClient.Create(nil);
// IdTCPClient1.ReuseSocket := rsOSDependent;
 IdTCPClient1.Host := '127.0.0.1';
 IdTCPClient1.Port := 10001;
// IdTCPClient1.OnWorkBegin := IdTCPClient1OnWorkBegin;
end;

procedure TClientThread.Execute;
var
  MIRec: TDatagram;
  msRecInfo: TMemoryStream;
  i,k:integer;
  Client1: TIdTCPClient;
  recieve:byte;
  respstream: TMemoryStream;
begin
  ClientConnection := TClient.Create;
  ClientConnection.IdTCPClient1.Connect;
  for k := 1 to 5 do begin

  if ClientConnection.IdTCPClient1.Connected then begin
{   MIRec.DataSize := 64;
   for i:=0 to MIRec.DataSize do
    MIRec.data[i] := i;
   for i:=129 to 4096 do MIRec.data[i] := 0;}
   MIRec.Proto := 1;
   MIRec.Command :=1;
  try
    msRecInfo := TMemoryStream.Create;
    msRecInfo.WriteBuffer(MIRec, SizeOf(MIRec));
    msRecInfo.Position := 0;
    ClientConnection.IdTCPClient1.IOHandler.Write(msRecInfo, msRecInfo.Size, true);
  finally
    msRecInfo.Free;
  end;
  end;
  end
 end;




end.

You are misusing Bindings.Add() and thus are creating 3 bindings:

127.0.0.1:10001
127.0.0.1:0
0.0.0.0:10002

I'm sure that is NOT what you really wanted.

As for your question - it depends on what your server needs to do.

If the server only responds to client commands then you can write a response directly in the OnExecute event after reading a command. A client can read the response immediately after sending a command. This is the typical usage.

If the server only sends unsolicited data to clients, then you can Lock() the server's Contexts list when needed, locate the desired connection and write to it, then Unlock() the list. A client will have to be reading asynchrously, such as in a thread, to read these messages.

If the server needs to do both , then this gets tricky. The best option is to implement a thread-safe outbound queue for each client, then you can put unsolicited data into the queue and have the OnExecute send the contents of the queue when it is safe to do so.

I have posted examples of all these in the Embarcadero and Indy forums many times before. Search around.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM