如何使用 System.Net.Socket 中的 TSocket 库在 RAD Studio 中编写跨平台异步套接字服务器?

问题描述 投票:0回答:1

简介

一般来说,RAD Studio 中的文档非常清晰,几乎每个场景都有很好的示例,在这种情况下我不知所措,文档中有以下关于 TSocket 的内容:

要将您的套接字用作服务器套接字:

  • 将您的套接字绑定到本地适配器。
  • 配置您的套接字以启动
  • 监听传入连接。
  • 接受传入连接。
  • 与远程套接字交换数据:从远程套接字接收数据。
  • 向远程套接字发送数据。
  • 关闭插座。

现在一切都很好,但是您实际上如何做到这一点以及如何使用这些方法并将它们结合在一起。通过遵循 Microsoft MSDN 的文档,我能够获得单个连接来工作。

单连接解决方案

这是我“工作”的第一个解决方案:

program SocketServer;

{$APPTYPE CONSOLE}

{$R *.res}

uses
  System.SysUtils, System.Net.Socket, System.Types;

var Socket: TSocket;

begin
  WriteLn('Starting Socket');
  Socket := TSocket.Create(TSocketType.TCP);
  Socket.Listen('127.0.0.1', '', 9006); //Very important ... second param is service

  try
    try
      var Connection := Socket.Accept(); //Waits until you connect - seems to be blocking

      while True do //All the examples have this
      begin
        WriteLn('Listening for data');
        var Bytes := Connection.Receive(); //Many ways to do this, opted for the simplest
        if StringOf(Bytes) <> '' then //Probably could have made this more optimal but it works
        begin
          WriteLn('Received: ' +StringOf(Bytes));
          WriteLn('Sent: OK');
          Connection.Send('OK');
        end;
        Sleep(1000); //Added this to give the processor a break
      end;
    finally
      Socket.Free;
    end;
  except
    On E:Exception do
    begin
      WriteLn('Exception happened:'+E.Message);
    end;
  end;

end.

如果您想处理来自单个连接的消息,该应用程序可以正常工作。我正在使用telnet进行测试,如果我连接多次似乎不起作用:

telnet localhost 9006

如果我输入一堆字符并按 Enter 键,我会得到响应。 这应该如何异步工作,或者我如何让它以异步方式工作,以便我可以接受多个连接。 在这个阶段,任何基本的解决方案/指向正确方向的点都会很棒,我可以从那里进行改进。我也不清楚连接何时应关闭或如何在不导致访问冲突或内存泄漏的情况下关闭连接。我也需要“退出”主循环,而不是无限循环的忠实拥护者......

在回答这个问题之前

  • 我并不是在寻找“使用 Indy 组件”作为解决方案,我已经在 Indy 中使用了这个,但当涉及到支持它所需的库时,它并不是非常“跨平台”。
  • 我不是在寻找第三方解决方案的链接,他们已经用它制作了组件,当然我可以花费 100-300 美元购买即时解决方案,但代码已经在 RAD Studio 中,所以它应该很容易使用?

提前感谢您对此问题提供任何明确的解决方案。 如果我弄清楚了这一点,我会自己回答这个问题,并欢迎就如何改进提出意见。

sockets delphi asynchronous delphi-11-alexandria delphi-12-athens
1个回答
0
投票

TSocket.Accept()
方法确实是阻塞的,它会等待直到接受新客户端,除非您为其提供
Timeout

在此模式下,您必须在单独的线程中为客户端

TSocket
提供服务,以便
Accept()
循环可以返回等待下一个客户端(这与 Indy 的
TIdTCPServer
内部运行的模型相同)。

对于您要查找的内容,请改用

TSocket.BeginAccept()
方法,该方法异步运行。 您可以提供一个回调,当新客户端被接受时会收到通知,或者您可以收到一个可以定期轮询的
IAsyncResult
。 不管怎样,当接受操作完成后,调用
TSocket.EndAccept()
来获取接受的客户端
TSocket
。 然后,您可以使用
TSocket.BeginReceive()
TSocket.BeginSend()
方法(以及相应的
TSocket.End...()
方法)与该客户端进行异步通信。

© www.soinside.com 2019 - 2024. All rights reserved.