[英]How to continuously send messages with TIdTCPServer?
我需要创建一个delphi应用程序,当它启动时,服务器也会启动并立即开始发送消息,但我还没有找到示例或教程,近5000页的Indy手册并没有让我明白我是怎么做的能做到这一点......
This example uses a Delphi 2009 VCL application with a main form, which contains only one visual component, a TMemo named “MemoLog”. 此示例使用带有主窗体的Delphi 2009 VCL应用程序,该窗体仅包含一个可视组件,名为“MemoLog”的TMemo。
Client and server are both started in the FormCreate event. 客户端和服务器都在FormCreate事件中启动。 Note that the client code does not handle connection loss, but this can be implemented with a separate re-connect loop within the thread.
请注意,客户端代码不处理连接丢失,但这可以通过线程内的单独重新连接循环来实现。
procedure TServerPushExampleForm.FormCreate(Sender: TObject);
begin
ExampleServer := TMyPushServer.Create;
ExampleServer.DefaultPort := 8088;
ExampleServer.Active := True;
ExampleClient := TMyPushClientThread.Create('localhost', 8088,
MemoLog.Lines);
end;
The server code uses a TIdTCPCustomServer subclass which waits for a random time and then sends a string to the client. 服务器代码使用TIdTCPCustomServer子类,该子类等待随机时间,然后将字符串发送到客户端。
function TMyPushServer.DoExecute(AContext: TIdContext): Boolean;
begin
Result := inherited;
// simulate hard work
Sleep(Random(3000));
AContext.Connection.IOHandler.WriteLn(
'Completed at ' + TimeToStr(Now), IndyTextEncoding_UTF8);
end;
The client code uses a TThread subclass to run asynchronously without blocking the main VCL thread. 客户端代码使用TThread子类异步运行,而不会阻塞主VCL线程。 It contains a private TIdTCPClient instance, and periodically tries to receive a string from the connection.
它包含一个私有TIdTCPClient实例,并定期尝试从连接接收字符串。
...
S := TCPClient.IOHandler.ReadLn(IndyTextEncoding_UTF8);
...
Below is the full code for the example main form. 下面是示例主窗体的完整代码。
unit Unit1;
interface
uses
IdCustomTCPServer, IdTCPClient, IdContext,
SysUtils, Classes, Forms, StdCtrls, Controls;
type
TMyPushClientThread = class(TThread)
private
TCPClient: TIdTCPClient;
FLog: TStrings;
public
constructor Create(AHost: string; APort: Word; ALog: TStrings);
destructor Destroy; override;
procedure Execute; override;
end;
TMyPushServer = class (TIdCustomTCPServer)
protected
function DoExecute(AContext: TIdContext): Boolean; override;
end;
TServerPushExampleForm = class(TForm)
MemoLog: TMemo;
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
ExampleClient: TMyPushClientThread;
ExampleServer: TMyPushServer;
end;
var
ServerPushExampleForm: TServerPushExampleForm;
implementation
uses
IdGlobal;
{$R *.dfm}
procedure TServerPushExampleForm.FormCreate(Sender: TObject);
begin
ExampleServer := TMyPushServer.Create;
ExampleServer.DefaultPort := 8088;
ExampleServer.Active := True;
ExampleClient := TMyPushClientThread.Create('localhost', 8088, MemoLog.Lines);
end;
procedure TServerPushExampleForm.FormDestroy(Sender: TObject);
begin
ExampleServer.Free;
ExampleClient.Terminate;
ExampleClient.WaitFor;
ExampleClient.Free;
end;
{ TMyPushServer }
function TMyPushServer.DoExecute(AContext: TIdContext): Boolean;
begin
Result := inherited;
// simulate hard work
Sleep(Random(3000));
AContext.Connection.IOHandler.WriteLn(
'Completed at ' + TimeToStr(Now), IndyTextEncoding_UTF8);
end;
{ TMyPushClientThread }
constructor TMyPushClientThread.Create(AHost: string; APort: Word; ALog: TStrings);
begin
inherited Create(False);
FLog := ALog;
TCPClient := TIdTCPClient.Create;
TCPClient.Host := AHost;
TCPClient.Port := APort;
TCPClient.ReadTimeout := 500;
end;
destructor TMyPushClientThread.Destroy;
begin
TCPClient.Free;
inherited;
end;
procedure TMyPushClientThread.Execute;
var
S: string;
begin
TCPClient.Connect;
while not Terminated do
begin
S := TCPClient.IOHandler.ReadLn(IndyTextEncoding_UTF8);
if not TCPClient.IOHandler.ReadLnTimedout then
begin
TThread.Queue(nil,
procedure
begin
FLog.Append(S);
end);
end;
end;
TCPClient.Disconnect;
end;
end.
(From https://mikejustin.wordpress.com/2014/04/19/indy-10-tidtcpserver-server-side-message-push-example/ ) (来自https://mikejustin.wordpress.com/2014/04/19/indy-10-tidtcpserver-server-side-message-push-example/ )
The way that Indy works is to have the client (TidTCPClient) connect to the server (TidTCPServer) and then exchange data between them, back-and-forth until the connection is terminated either willfully or by premature disconnect. Indy工作的方式是让客户端(TidTCPClient)连接到服务器(TidTCPServer),然后在它们之间来回交换数据,直到连接被故意或过早断开连接。
I am only referring to the actual Indy TCP components here and not to the way you see your applications. 我这里仅指的是实际的Indy TCP组件,而不是您看到应用程序的方式。
At the application level you might consider an application the server app and another the client app but both can/may contain both TidTCPClient and TidTCPServer components with which they communicate with other apps. 在应用程序级别,您可以将应用程序视为服务器应用程序,将另一个应用程序视为客户端应用程序,但两者都可以/可能包含与其他应用程序通信的TidTCPClient和TidTCPServer组件。 This means that the server app can initiate a connection to a client app via the server app's TidTCPClient component and the client app will receive the connection via its TidTCPServer component.
这意味着服务器应用程序可以通过服务器应用程序的TidTCPClient组件启动与客户端应用程序的连接,客户端应用程序将通过其TidTCPServer组件接收连接。 This would be a possible solution but keep in mind that generally clients are dynamic and ever changing while servers are usually static and as such it will be a mission to keep track of where clients are.
这可能是一种可能的解决方案,但要记住,通常客户端是动态的,而且不断变化,而服务器通常是静态的,因此跟踪客户端的位置是一项任务。 Too many headaches and too much work as well.
太多的头痛和太多的工作。
So I think it is better to have clients keep track of their rarely changing servers and as such it is better to have a TidTCPServer component for the server app and have it wait for client connections before it starts to send messages. 因此,我认为最好让客户端跟踪他们很少更改的服务器,因此最好为服务器应用程序安装一个TidTCPServer组件,并让它在开始发送消息之前等待客户端连接。
So to implement; 所以要实施; your clients would have to constantly try to connect to the server at regular intervals until it finds the server.
您的客户必须不断尝试定期连接到服务器,直到找到服务器。 The server can then send as many messages as it wants until asked to stop or until premature disconnect in which case the cycle will be restarted.
然后,服务器可以发送任意数量的消息,直到被要求停止或直到过早断开,在这种情况下,循环将重新启动。 There are ways in Indy to keep track of client connections and you can keep an internal list of the clients through those means.
Indy有一些方法可以跟踪客户端连接,您可以通过这些方式保留客户端的内部列表。 This makes more sense.
这更有意义。 It is the way that most client-server apps work.
这是大多数客户端 - 服务器应用程序的工作方式。 Just think of Skype and any Web Server.
想想Skype和任何Web服务器。 The clients contacts the server and receives data if needs be.
客户端联系服务器并在需要时接收数据。
At the server side: 在服务器端:
At the client side: 在客户端:
There are many examples for this type of operation. 这种类型的操作有很多例子。 You must try first and if you struggle you can always ask questions specific to the problem you are having.
你必须先尝试,如果你挣扎,你总能提出具体问题的问题。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.