每当您拨打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;
谢谢您的回答!我将这些软件包合并为一个大包,我将它作为一个流读取,现在它可以工作。谢谢! – hunyadym 2012-02-09 22:23:44