在客户端delphi上设置SOAP请求的超时限制?

时间:2015-12-07 14:16:19

标签: delphi soap firemonkey

我的网络服务是用delphi编写的。有时其中一些需要很长时间才能做出回应我想在客户端为他们设置30秒的超时时间。 鉴于我所有的服务器调用都是通过单独的线程完成的,我如何实现超时设置。

我目前正在使用SELECT c.id, dsv63.name AS 102进行HTTP请求。

2 个答案:

答案 0 :(得分:1)

您没有说明您用于沟通的组件。

我使用THTTPReqResp进行SOAP通信并执行此操作:

constructor TEWSSOAPMessage.Create(AWebserviceURL,AUserName,APassword: String; AExchangeTimeOutConnect,AExchangeTimeOutSend,AExchangeTimeOutReceive: Integer);
begin
   FSoapRequest := TStringStream.Create('',TEncoding.UTF8);
   FSoapRequest.Position := 0;
   FSoapResponse := TStringStream.Create('',TEncoding.UTF8);
   FSoapResponse.Position := 0;

   FReqResp := THTTPReqResp.Create(nil);
   FReqResp.URL := AWebserviceURL;
   FReqResp.UserName := AUserName;
   FReqResp.Password := APassword;
   if AExchangeTimeOutConnect > 0 then FReqResp.ConnectTimeout := AExchangeTimeOutConnect;
   if AExchangeTimeOutSend    > 0 then FReqResp.SendTimeout    := AExchangeTimeOutSend;
   if AExchangeTimeOutReceive > 0 then FReqResp.ReceiveTimeout := AExchangeTimeOutReceive;
   ...
end;

如果我指定0,则会留下默认超时。
我填写FSoapRequest,然后当我执行'我的TEWSSOAPMessage:

procedure TEWSSOAPMessage.Execute;
begin
   try
      FExecTime := GetTickCount;
      FReqResp.Execute(FSoapRequest,FSoapResponse);
      FExecTime := GetTickCount - FExecTime;
      ...
   except
      on E:Exception do
      begin
         // WinINet error codes https://msdn.microsoft.com/en-us/library/microsoft.exchange.webservices.data.serviceerror%28v=exchg.80%29.aspx
         if (E is ESOAPHTTPException) and (ESOAPHTTPException(E).StatusCode = ERROR_INTERNET_TIMEOUT) then
         begin
            FExecTime := GetTickCount - FExecTime;
            FErrorMsg := Format(' TIMEOUT (%d msec) %s',[FExecTime,sErrExchangeTimeOutINI]);
         end;
         ...
      end;
   end;
end; { Execute }

对于Delphi XE2 ERROR_INTERNET_TIMEOUTWinapi.WinInet中声明,ESOAPHTTPExceptionSoap.SOAPHTTPTrans

中声明

作为旁注,请确定您的超时时间(来自here):

procedure TFrmWininetTimeOuts.FormShow(Sender: TObject);
var
  hSession     : HINTERNET;
  dwTimeOut    : DWORD;
  lBuflen      : Cardinal;
begin
  hSession := InternetOpen('usersession', INTERNET_OPEN_TYPE_PRECONFIG, nil, nil, 0);
  if not Assigned(hSession) then Exit;
  try
    lBufLen := SizeOf(dwTimeOut);
    if InternetQueryOption(hSession, INTERNET_OPTION_CONNECT_TIMEOUT, @dwTimeOut, lBufLen) then
       Edit1.Text := IntToStr(dwTimeOut);
    if InternetQueryOption(hSession, INTERNET_OPTION_SEND_TIMEOUT, @dwTimeOut, lBufLen) then
       Edit2.Text := IntToStr(dwTimeOut);
    if InternetQueryOption(hSession, INTERNET_OPTION_RECEIVE_TIMEOUT, @dwTimeOut, lBufLen) then
       Edit3.Text := IntToStr(dwTimeOut);
  finally
    InternetCloseHandle(hSession);
  end;
end;

答案 1 :(得分:1)

首先,如果您还没有设置超时:

var
  MyRIO: THTTPRIO;
begin
  MyRio := ... 
  MyRIO.HTTPWebNode.ConnectTimeout:=x; 
  MyRIO.HTTPWebNode.SendTimeout :=x; 
  MyRIO.HTTPWebNode.ReceiveTimeout:=x; 
end;

如果这不起作用,请进一步挖掘。

据我所知,THTTPRIO的问题在于,至少在Windows上,它使用或曾经使用过WinINET,而WinINET中有许多潜在的错误,包括无法尊重所请求的任何超时。出于这个原因,我放弃了使用WinINET的任何东西。您使用的是哪个版本的Delphi?我想在某些时候,THTTPRIO可能已经从WinINET(这是废话)转移到WinHTTP(这很好),但是根据你的Delphi版本,你可能想要检查一下发生了什么。在Android和iOS上,当然,在Mac firemonkey上,WinINET是不可能的,但如果你在Windows上进行测试及其出现故障,请考虑这种可能性。我相信,通过Delphi XE8和10西雅图,默认情况下,THINTPRIO不会使用WinINET,但是我无法在此找到文档。