Indy TIdTCPServer TIdTCPClient数据交换

时间:2014-04-26 20:47:48

标签: delphi tcp ip indy delphi-xe6

我花了一些时间编写一个简单的应用程序来在TIdTCPServerTIdTCPClient之间交换数据。但现在我被卡住了 我可以将数据从TIdTCPClient发送到TIdTCPServer并进行处理。
但是不知道,官方文档没有提供任何线索如何从TIdTCPServer发送数据并在TIdTCPClient处理它。请指教。

我的代码很简单:

主要申请:

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;

服务器线程:

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.

客户线程:

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.

1 个答案:

答案 0 :(得分:3)

您滥用Bindings.Add()因此正在创建 3 绑定:

127.0.0.1:10001
127.0.0.1:0
0.0.0.0:10002

我确定这不是你真正想要的。

至于你的问题 - 这取决于你的服务器需要做什么。

如果服务器响应客户端命令,那么您可以在读取命令后直接在OnExecute事件中编写响应。客户端可以在发送命令后立即读取响应。这是典型用法。

如果服务器向客户端发送未经请求的数据,则可以在需要时Lock()服务器的Contexts列表,找到所需的连接并写入它,然后Unlock()列表。客户端必须异步读取,例如在线程中读取这些消息。

如果服务器需要两者,那么这就变得棘手了。最好的选择是为每个客户端实现一个线程安全的出站队列,然后你可以将未经请求的数据放入队列,并让OnExecute在安全的情况下发送队列的内容。

我曾多次在Embarcadero和Indy论坛上发布所有这些的例子。搜索。

相关问题