gpt4 book ai didi

delphi - 当发送包过于频繁时,Indy TCPServer 无法从 TCPClient 接收所有包

转载 作者:行者123 更新时间:2023-12-03 15:29:29 27 4
gpt4 key购买 nike

我的 Indy TCP 连接有问题。我使用 Turbo Delphi 2006 和 Indy 10。我想从 idTCPClient 向 idTCPServer 发送多个 TCP 包。

当我只想发送一个包,或者我在函数的两次调用之间插入 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

感谢您提前的答复!

最佳答案

每次调用Connect()时,您都会创建一个新连接,并且TIdTCPServer将启动一个新线程来处理该连接(除非您启用线程池,那是)。那是你真正想要的吗?让客户端将连接保持打开状态一段时间并尽可能重用现有连接会更有效。仅当您确实不再需要它时才断开连接,例如当它闲置一段时间时。建立新连接对两端来说都是一项昂贵的操作,因此您应该尽可能减少该开销。

在客户端,当您调用 Write(data) 时,它将发送整个 TIdBytes,但您不会发送该 TIdBytes 的长度 到服务器,以便它知道需要多少字节。 TIdIOHandler.Write(TIdBytes) 不会为您执行此操作,您必须手动执行此操作。

在服务器端,您告诉 ReadBytes() 一次仅读取 4 个字节。在每个 4 字节 block 之后,您将退出 OnExecute 事件处理程序并等待它再次被调用以读取下一个 4 字节 block 。除非客户端源TIdBytes的长度是4的偶数倍,否则ReadBytes()在尝试读取时会引发异常(导致服务器断开连接)客户端的最后一个 block 小于 4 个字节,因此您的服务器代码将不会接收该 block 。

试试这个:

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;

关于delphi - 当发送包过于频繁时,Indy TCPServer 无法从 TCPClient 接收所有包,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9169494/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com