如何在Delphi XE中的SOAPServerwithINDYVCL中处理Socket错误10053

时间:2013-07-02 08:43:20

标签: soap indy

我在Delphi XE中创建了一个SOAPServerwithINDYVCL。当客户端由于客户端超时或网络连接丢失等原因而与服务器断开连接时。 我在服务器端收到错误,因为Socket Error 10053 - 软件导致连接中止。

此错误弹出并阻止我的服务器线程。

我还通过SOAPDMServerIndy的演示检查了这一点。在这里,如果我启动服务器,连接客户端,在服务器响应之前断开客户端我得到套接字错误。

任何人都知道如何处理此异常?

1 个答案:

答案 0 :(得分:0)

即使在这个时候,这个问题仍然存在。因为此代码:

procedure TWebRequestHandler.HandleException(Sender: TObject);
var
  Handled: Boolean;
  Intf: IWebExceptionHandler;
begin
  Handled := False;
  if ExceptObject is Exception and
    Supports(Sender, IWebExceptionHandler, Intf) then
    try
      Intf.HandleException(Exception(ExceptObject), Handled);
    except
      Handled := True;
      System.SysUtils.ShowException(ExceptObject, ExceptAddr);
    end;
  if (not Handled) then
    System.SysUtils.ShowException(ExceptObject, ExceptAddr);
end;

Intf.HandleException(Exception(ExceptObject), Handled)行调用TCustomWebDispatcher.HandleException过程。此过程检查应用程序的TWebModule子代中是否存在OnException事件处理程序。如果存在(我建议这样做),则将var参数'Handled'设置为true来调用事件处理程序过程。

procedure TCustomWebDispatcher.HandleException(E: Exception; var Handled: Boolean);
begin
  Handled := False;
  if Assigned(FOnException) then
  begin
    Handled := True;
    if Response <> nil then
      Response.StatusCode := 500; { Allow the user to override the StatusCode }
    FOnException(Self, E, Handled);
    if Handled and (Response <> nil) then
      Response.SendResponse;
  end;
  if not Handled then
    if Response <> nil then
    begin
      Response.Content := Format(sInternalApplicationError, [E.Message, Request.PathInfo]);
      if not Response.Sent then
      begin
        Response.StatusCode := 500;
        Response.SendResponse;
      end;
      Handled := True;
    end;
end;

处理程序返回时有两种情况:

  1. 处理为真;将发送导致新异常的响应。这将被传播回调用代码(第一个块中的过程),因此将调用ShowException。

  2. Handled为False; Response <> nil的计算结果为True,因此当Response.Sent为False时,将会发生相同的事情。

我通过尝试从OnException事件处理程序发送响应来解决此问题。如果失败,则会引发异常。在那种情况下,我会将TWebModule的后代的只读属性“ Response”的“ FResponse”字段设置为“ nil”。但是,此字段是私有字段,因此我使用了一些rtti来访问它。

procedure TwbmWebBrokerServerModule.UnlinkResponseObject;
begin
  inherited;

  TRTTIContext.Create.GetType(ClassInfo).GetField('FResponse').SetValue(Self, TValue.From(nil));
end;

procedure TwbmWebBrokerServerModule.WebModuleException(Sender: TObject; E: Exception; var Handled: Boolean);
begin
  uVMI_Tools.AppendToLog(E.Message + ' (' + Request.PathInfo + ')');

  if Request.Accept.Contains(CONTENTTYPE_APPLICATION_JSON) then
  begin
    Response.Content := StringToJSON(E.Message);
    Response.ContentType := CONTENTTYPE_APPLICATION_JSON;
  end
  else
    Response.Content := E.Message;

  try
    Response.SendResponse;
  except
    UnlinkResponseObject;
  end;
end;

因此,当发送响应时发生异常时,属性“ Response”设置为nil,因此不会尝试再次发送响应。

不需要破坏响应对象,将nil设置为足够。这是因为Response对象是在TIdCustomHTTPServer类中创建的,该类刚刚将其传递给TWebModule子孙。 (实际上是TWebModule的父类TCustomWebDispatcher)