我有Indy TCP连接问题。我使用Turbo Delphi 2006和Indy 10。 我想从idTCPClient发送多个TCP包到idTCPServer。
当我只想发送一个包,或者在两次调用函数之间插入sleep(100)命令时,它工作正常。但是,如果我过于频繁地调用此函数,则每次都不会调用服务器的onExecute。
我的发送代码:
procedure SendData(var data: TIdBytes) ;
begin
FormMain.IdTCPClient.Connect ;
FormMain.IdTCPClient.Socket.Write(data);
FormMain.IdTCPClient.Disconnect ;
end ;
我多次调用此函数(每秒5-10次),并希望在我的服务器应用程序中处理所有这些包:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
data: TIdBytes ;
begin
AContext.Connection.IOHandler.ReadBytes(data, 4, false)
// processing data
end
提前感谢您的回答!
答案 0 :(得分:4)
每次调用Connect()
时,您都在创建一个新连接,TIdTCPServer
将启动一个新线程来处理该连接(除非您启用线程池,即)。那是你真正想要的吗?让客户端在一段时间内保持连接打开并尽可能多地重用现有连接会更有效。只有当你真的不再需要连接时才会断开连接,例如当它闲置一段时间时。建立新连接是两端都很昂贵的操作,所以你应该尽可能地减少这种开销。
在客户端,当您致电Write(data)
时,它会发送整个TIdBytes
,但您没有将TIdBytes
的长度发送到服务器,因此它知道有多少要期望的字节数。 TIdIOHandler.Write(TIdBytes)
不会为您执行此操作,您必须手动执行此操作。
在服务器端,您告诉ReadBytes()
一次只读取4个字节。在每个4字节的块之后,您将退出OnExecute
事件处理程序并等待再次调用它以读取下一个4字节的块。除非客户端的源TIdBytes
的长度是4的偶数倍,否则ReadBytes()
会在尝试读取客户端的最后一个块时引发异常(导致服务器断开连接) 4个字节,因此您的服务器代码将不会收到该块。
请改为尝试:
procedure SendData(var data: TIdBytes) ;
begin
FormMain.IdTCPClient.Connect;
try
FormMain.IdTCPClient.IOHandler.Write(Longint(Length(data)));
FormMain.IdTCPClient.IOHandler.Write(data);
finally
FormMain.IdTCPClient.Disconnect;
end;
end;
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
data: TIdBytes;
begin
with AContext.Connection.IOHandler do
ReadBytes(data, ReadLongint, false);
// process data
end;
话虽如此,如果因任何原因更改客户端代码以发送TIdBytes
长度不是一个选项,那么请改用此服务器代码:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
LBytes: Integer;
data: TIdBytes;
begin
// read until disconnected. returns -1 on timeout, 0 on disconnect
repeat until AContext.Connection.IOHandler.ReadFromSource(False, 250, False) = 0;
AContext.Connection.IOHandler.InputBuffer.ExtractToBytes(data);
// process data
end;
或者:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
strm: TMemoryStream;
data: TIdBytes;
begin
strm := TMemoryStream.Create;
try
// read until disconnected
AContext.Connection.IOHandler.ReadStream(strm, -1, True);
strm.Position := 0;
ReadTIdBytesFromStream(strm, data, strm.Size);
finally
strm.Free;
end;
// process data
end;
或者:
procedure TFormMain.IdTCPServerMainExecute(AContext: TIdContext);
var
strm: TMemoryStream;
begin
strm := TMemoryStream.Create;
try
// read until disconnected
AContext.Connection.IOHandler.ReadStream(strm, -1, True);
// process strm.Memory up to strm.Size bytes
finally
strm.Free;
end;
end;