我花了一些时间编写一个简单的应用程序来在TIdTCPServer
和TIdTCPClient
之间交换数据。但现在我被卡住了
我可以将数据从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.
答案 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论坛上发布所有这些的例子。搜索。