gpt4 book ai didi

delphi - 使用mORMot框架在服务器和客户端之间发送消息

转载 作者:行者123 更新时间:2023-12-01 21:10:25 24 4
gpt4 key购买 nike

mORMot Framework ( www.synopse.info ) 添加了对 WebSockets 的支持,包装上还有一个关于 WebSockets 的演示(示例 31)。在此示例中,客户端向服务器发送一条消息,然后向客户端回复一条新消息。我想使用这个库来做到这一点:

  1. 客户端向服务器发送消息并发送 IP 地址(无需等待服务器发送消息);
  2. 服务器可以通过IP地址向单个客户端发送消息;

注意:IP地址仅用于识别客户端。我还可以使用一个唯一的名称。

类似于客户端和服务器之间的 LAN 聊天。我不明白如何编辑样本n。 31 去做吧。该示例基于接口(interface)。

最佳答案

无需存储 IP 或任何低级实现参数(顺便说一下,IP 无法以唯一的方式识别连接:多个客户端可能共享相同的 IP)。

mORMot框架中,异步回调是通过接口(interface)参数实现的。在服务器端,此参数的每个实例实际上都是一个“假”类实例,链接到输入连接,能够通过其接口(interface)方法回调客户端。

这是一种非常简单的实现回调的方法 - 事实上,这是在服务器端实现 SOLID 回调的好方法,并且 mORMot 框架允许在客户端/服务器中发布此机制方式,通过使用WebSockets

所以你首先定义回调接口(interface)和服务接口(interface):

  IChatCallback = interface(IInvokable)
['{EA7EFE51-3EBA-4047-A356-253374518D1D}']
procedure BlaBla(const pseudo, msg: string);
end;

IChatService = interface(IInvokable)
['{C92DCBEA-C680-40BD-8D9C-3E6F2ED9C9CF}']
procedure Join(const pseudo: string; const callback: IChatCallback);
procedure BlaBla(const pseudo,msg: string);
procedure CallbackReleased(const callback: IInvokable);
end;

然后,在服务器端,每次调用 IChatService.Join() 都会订阅内部连接列表:

  TChatService = class(TInterfacedObject,IChatService)
protected
fConnected: array of IChatCallback;
public
procedure Join(const pseudo: string; const callback: IChatCallback);
procedure BlaBla(const pseudo,msg: string);
procedure CallbackReleased(const callback: IInvokable);
end;

procedure TChatService.Join(const pseudo: string;
const callback: IChatCallback);
begin
InterfaceArrayAdd(fConnected,callback);
end;

然后,对 IChatService.BlaBla() 方法的远程调用应该广播到所有连接的客户端,只需调用 IChatCallback.BlaBla() 方法即可:

procedure TChatService.BlaBla(const pseudo,msg: string);
var i: integer;
begin
for i := 0 to high(fConnected) do
fConnected[i].BlaBla(pseudo,msg);
end;

请注意,对 IChatCallback.BlaBla() 的所有循环调用都将通过 WebSockets 以异步和非阻塞的方式进行,因此即使在巨大的情况下客户端数量,IChatService.BlaBla() 方法不会阻塞。在消息数量较多的情况下,框架甚至能够将通知消息收集到单个消息中,以减少资源使用。

当客户端回调实例被释放(无论是显式释放,还是连接中断)时,服务器将调用以下方法,因此可用于取消订阅通知:

procedure TChatService.CallbackReleased(const callback: IInvokable);
begin
InterfaceArrayDelete(fConnected,callback);
end;

在服务器端,您可以这样定义服务:

  Server.ServiceDefine(TChatService,[IChatService],sicShared).
SetOptions([],[optExecLockedPerInterface]);

这里,已经设置了optExecLockedPerInterface选项,这样所有的方法调用都会成为线程安全的,这样就可以并发访问内部fConnected[]列表确保安全。

在客户端,您实现 IChatCallback 回调接口(interface):

type
TChatCallback = class(TInterfacedCallback,IChatCallback)
protected
procedure BlaBla(const pseudo, msg: string);
end;

procedure TChatCallback.BlaBla(const pseudo, msg: string);
begin
writeln(#13'@',pseudo,' ',msg);
end;

然后您订阅您的远程服务,如下所示:

var Service: IChatService;
callback: IChatCallback;
...
Client.ServiceDefine([IChatService],sicShared);
if not Client.Services.Resolve(IChatService,Service) then
raise EServiceException.Create('Service IChatService unavailable');
...
callback := TChatCallback.Create(Client,IChatCallback);
Service.Join(pseudo,callback);
...
try
repeat
TextColor(ccLightGray);
readln(msg);
if msg='' then
break;
Service.BlaBla(pseudo,msg);
until false;
finally
callback := nil;
Service := nil; // release the service local instance BEFORE Client.Free
end;

如果与现有的客户端/服务器 SOA 解决方案(Delphi、Java、C# 甚至 Go 或其他框架)进行比较,这种基于接口(interface)的回调机制听起来非常独特且易于使用。当然,这项工作从 Delphi 6 到 XE7,并且在 Linux 下也可以通过 FPC 或 CrossKylix 实现。

我已在我们的存储库中上传了完整的示例源代码,均为 the server side applicationthe client side .

关于delphi - 使用mORMot框架在服务器和客户端之间发送消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29462334/

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