【问题标题】:Indy TCPServer OnExecute analog of HTTPServer OnCommandGetHTTPServer OnCommandGet 的 Indy TCPServer OnExecute 模拟
【发布时间】:2014-07-27 18:51:36
【问题描述】:

是否可以让我的TCPServer.OnExecute 事件的行为方式与HTTPServer.OnCommandGet 的行为方式相同:

procedure TMainForm.HttpServerCommandGet(AContext: TIdContext;
  ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
begin
  AResponseInfo.ResponseNo := 200;
  AResponseInfo.ContentType := 'text/plain';
  AResponseInfo.ContentText := 'Hello';
end; 

我试过这个:

procedure TMainForm.TCPServerExecute(AContext: TIdContext);
begin
  AContext.Connection.IOHandler.WriteLn('Hello');
end;

但它会无限次向浏览器发送“Hello”,直到我使服务器处于非活动状态。

【问题讨论】:

    标签: delphi indy tcpserver


    【解决方案1】:

    TIdHTTPServer 在从客户端读取完整的 HTTP 请求之前不会触发 OnCommand... 事件。

    您的TIdTCPServer 根本没有读取任何请求。

    TIdTCPServer.OnExecute 是一个循环事件。它在连接的生命周期内连续触发。事件处理程序的职责是决定在每次循环迭代中做什么,并提供适合正在实现的通信协议的任何必要的读/写逻辑。

    在您的示例中,您所做的只是在每次循环迭代时编写一行文本,这就是为什么您会看到浏览器中出现无穷无尽的行。您的事件处理程序逻辑需要比这更有条理。这就是协议的全部内容。在您的情况下,由于您正在与 Web 浏览器进行通信,因此您需要实现 HTTP protocol(这就是 TIdHTTPServer 为您所做的)。

    【讨论】:

      【解决方案2】:

      在 TCP 连接期间循环调用 execute 方法。这对于服务器推送应用程序来说是可以的(除了应该限制消息发送以避免服务器过载)。

      如果您想实现请求/回复协议,请从 ReadLn(或任何其他与您的协议匹配的 Read 方法)开始。这将阻止执行,直到客户端发送请求。

      【讨论】:

      • 您能举个例子吗,因为AContext.Connection.IOHandler.ReadLn; AContext.Connection.IOHandler.WriteLn('Hello'); 向浏览器发送了 7 次“Hello”,而那是在我将 TCPServer 设为非活动状态之后。
      • 如果ReadLn没有读取任何数据,它会返回一个空字符串。你检查过这个吗?如果它返回一个空字符串,这意味着它在客户端发送数据之前超时。在这种情况下,不要发回响应。
      • @Roman_Bezjak:Web 浏览器会使用 HTTP protocol 与您的 TIdTCPServer 通信,其中包含请求标头中的文本行。这就是为什么您的ReadLn() 调用得到满足,而OnExecute 将继续循环直到没有更多行可读取。因此,如果您看到 7 个 hello,则浏览器的请求必须在其标头中包含 7 行。
      • @mjn: ReadLn() 仅在超时时才会返回空行,在这种情况下,它会在退出前将 ReadLnTimedOut 属性设置为 true。默认情况下,Indy 使用无限超时,因此您必须将 ReadTimeout 属性设置为其他值,或者将超时作为输入参数直接传递给 ReadLn()
      猜你喜欢
      • 2015-02-19
      • 1970-01-01
      • 1970-01-01
      • 2011-04-02
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多