我有一个应用程序(“服务器”),它每秒更新内存中的一个数据 block (大约 100k 字节)。
同一网络上的其他工作站上运行着 1 到 4 个“客户端”应用程序的其他实例,这些实例需要每秒读取相同的 100k 图像。
到目前为止,这是通过将图像写入服务器上的文件并让客户端通过网络从该文件读取来实现的。这多年来一直没有任何问题,但最近(与迁移到基于 Windows 8 的硬件同时发生)它出现了一个问题,即除一个节点之外的所有节点都无法访问该文件。退出在此节点上运行的客户端应用程序会释放该文件,然后每个人都可以再次访问该文件。
我仍然对这次锁定的原因感到困惑,但我想知道这是否可能是讨论的机制 here ,其中文件由于网络故障而未关闭。我认为让客户端通过 TCP/IP 请求数据可以避免这种情况。
除了客户端无法连接或读取数据之外,不需要任何握手 - 服务器只需要处理它的业务并通过抓取数据并发送它来响应请求。然而,我对实现这一目标的最佳架构还很模糊。 TidTCPClient 和 TidTCPServer 会削减它吗?我假设客户端会在线程中请求数据,但这是否意味着服务器需要连续运行线程来响应请求?
最佳答案
TIdTCPServer
是一个多线程组件。它的客户端在它为您管理的工作线程中运行。您所要做的就是实现 OnExecute
事件来发送数据。
TIdTCPClient
不是多线程组件。它运行在您使用它的任何线程中。因此,如果您需要连续读取数据,最好运行您自己的工作线程来处理读取。 Indy 有一个封装线程的 TIdThreadComponent
组件,或者您可以手动编写自己的 TThread
代码。
100K 并不是很多数据,因此我建议完全忘记该文件并在内存中分配一个缓冲区。您的 TIdTCPServer.OnExecute
事件处理程序可以在需要时从该缓冲区读取。我什至不会费心让客户端请求数据,只需让服务器不断将最新数据推送到事件客户端即可。
尝试这样的事情:
服务器:
var
Buffer: TIdBytes;
Lock: TMREWSync;
procedure TForm1.IdTCPServer1Execute(AContext: TIdContext);
begin
Lock.BeginRead;
try
AContext.Connection.IOHandler.Write(Buffer);
finally
Lock.EndRead;
end;
Sleep(1000);
end;
procedure TForm1.UpdateBuffer;
begin
Lock.BeginWrite;
try
// update the Buffer content as needed...
finally
Lock.EndWrite;
end;
end;
initialization
Lock := TMREWSync.Create;
SetLength(Buffer, 1024 * 100);
finalization
SetLength(Buffer, 0);
Lock.Free;
客户:
procedure TForm1.IdThreadComponent1Run(Sender: TIdThreadComponent);
var
Buffer: TIdBytes;
begin
IdTCPClient1.IOHandler.ReadBytes(Buffer, 1024 * 100);
// use Buffer as needed...
end;
procedure TForm1.Connect;
begin
IdTCPClient1.Connect;
try
IdThreadComponent1.Start;
except
IdTCPClient1.Disconnect;
raise;
end;
end;
procedure TForm1.Disconnect;
begin
IdTCPClient1.Disconnect;
IdThreadComponent1.Stop;
end;
关于Delphi 2007,Indy 10 - 用于单向传输数据 block 的最简单的 TCP/IP 设置是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29091238/