【问题标题】:TimeoutException thrown consuming WCF Service hosted in the Network使用网络中托管的 WCF 服务引发 TimeoutException
【发布时间】:2019-06-07 08:35:41
【问题描述】:

我正在编写一个 Web 应用程序,它将托管在 Raspberry PI 上的 Electron 中。 Raspberry PI 附加了一个指纹扫描仪,它返回一个字符串,我需要检查指纹是否已在另一台服务器上的数据库中注册。我通过调用网络上托管的 WCF 服务方法来执行此操作。
现在的问题是调用 WCF 服务时,我在 1 分钟后超时(默认超时),但当我在本地计算机上运行应用程序时它可以工作。

服务代码:

[ServiceContract(Namespace = "http://192.168.0.154:8733/GlauxSoft.SnackBox.WebService/")]
public interface IService
{
        [OperationContract]
        Fingerprint GetFingerprintByUniqueId(string uniqueId);
}

public class Service : IService
{
    public Fingerprint GetFingerprintByUniqueId(string uniqueId)
    {
        // This is just a DataBase call, nothing extraordinarily expensive
        using (EvidenceSessionHelper.CreateDefaultWebServiceSession())
        {
            return Fingerprint.MapAuthentifizierungToWebServiceFingerprint(QueryAuthentifizierung.GetFingerprintByUniqueId(uniqueId));
        }
    }
}

消费者代码:

[ServiceContract(Namespace = "http://192.168.0.154:8733/GlauxSoft.SnackBox.WebService/", ConfigurationName = "ISnackBoxService")]
public interface ISnackBoxService
{
    [OperationContract(
        Action ="http://192.168.0.154:8733/GlauxSoft.SnackBox.WebService/IService/GetFingerprintByUniqueId", 
        ReplyAction = "http://192.168.0.154:8733/GlauxSoft.SnackBox.WebService/IService/GetFingerprintByUniqueIdResponse")]
    Fingerprint GetFingerprintByUniqueId(string uniqueId);
}

public class ServiceClient : ClientBase<IService>, IService
{
    public SnackBoxServiceClient() : 
            base(GetDefaultBinding(), GetDefaultEndpointAddress())
    {
        Endpoint.Name = EndpointConfiguration.BasicHttpBinding_ISnackBoxService.ToString();
    }

    public enum EndpointConfiguration
    {
        BasicHttpBinding_ISnackBoxService
    }

    public Fingerprint GetFingerprintByUniqueId(string uniqueId)
    {
        return Channel.GetFingerprintByUniqueId(uniqueId);
    }
}

消费者是一个用 .NET Core 3 Preview 5 编写的 ASP.NET Razor 应用

我这样调用消费者代码:

var service = new ServiceClient();
var evdFingerprint = service.GetFingerprintByUniqueId("Test String"); // <-- Runs for 1 minute and throws the TimeoutException

这是堆栈跟踪:

System.TimeoutException:请求通道在 00:01:00 之后尝试发送超时。增加传递给 Request 调用的超时值或增加 Binding 上的 SendTimeout 值。分配给此操作的时间可能是较长超时的一部分。 ---> System.TimeoutException:对“http://192.168.0.154:8733/GlauxSoft.SnackBox.WebService/”的 HTTP 请求已超过分配的超时时间 00:01:00。分配给此操作的时间可能是较长超时的一部分。 在 System.ServiceModel.Channels.HttpChannelFactory`1.HttpClientRequestChannel.HttpClientChannelAsyncRequest.SendRequestAsync(消息消息,TimeoutHelper timeoutHelper) 在 System.ServiceModel.Channels.RequestChannel.RequestAsync(消息消息,TimeSpan 超时)

编辑:我已经做了一些进一步的测试,似乎对我的本地机器的任何 HTTP 请求都没有像 wget 192.168.0.154:5106 -o index.html 那样通过,并且使用wireshark 监控我的网络流量也没有向我显示对我的电脑的任何 GET 请求,并且转到 https://192.168.0.154:5106 也会超时。
但是,我可以 ping 我的本地电脑,甚至可以通过 SSH 连接到我的 Raspberry PI,我还可以与我的 Raspberry PI 建立 VNC 远程桌面会话

【问题讨论】:

    标签: c# wcf .net-core


    【解决方案1】:

    您可以通过多种方式在绑定中配置超时。在代码中,

        WSHttpBinding binding = new WSHttpBinding();
        binding.OpenTimeout = new TimeSpan(0, 10, 0);
        binding.CloseTimeout = new TimeSpan(0, 10, 0);
        binding.SendTimeout = new TimeSpan(0, 10, 0);
        binding.ReceiveTimeout = new TimeSpan(0, 10, 0);
    

    或在 web.config 中

    <configuration>
      <system.serviceModel>
        <bindings>
          <wsHttpBinding>
            <binding openTimeout="00:10:00" 
                     closeTimeout="00:10:00" 
                     sendTimeout="00:10:00" 
                     receiveTimeout="00:10:00">
            </binding>
          </wsHttpBinding>
        </bindings>
      </system.serviceModel>
    </configuration>
    

    【讨论】:

    • 我不想增加超时时间(因为我的身份验证服务器必须等待长达 10 分钟才能响应是可笑的)
    【解决方案2】:

    GetDefaultBinding()、GetDefaultEndpointAddress()

    希望您能与我分享与上述方法主体相关的更多细节。
    默认绑定的 ClientCredentailType 是什么?因为某些绑定与 Core(WS-* 绑定)不太兼容。另外,您在从另一台机器调用服务时是否修改了客户端的服务端点地址?
    在我看来,我们可以使用 Microsoft WCF Web Service Reference Provider 工具生成客户端代理,然后根据服务器端的绑定配置修改服务端点地址并显式提供客户端凭据。
    如果问题仍然存在,请随时告诉我。

    【讨论】:

    • GetDefaultBindingGetDefaultEndpointAddress 方法都返回正确的 IP 地址 (192.168.0.154),我通过 Visual Studio Enterprise 2019 Preview 3 中的“添加连接的服务”对话框选项生成了代码,能否详细说明如何明确提供客户端凭据?
    • 由于我们用于创建安全通道的绑定元素可以对客户端进行身份验证,因此绑定的配置可能需要客户端提供凭据。 docs.microsoft.com/en-us/dotnet/framework/wcf/… 例如,WsHttpBinding 默认要求客户端提供windows凭据(服务器的账号)。
    【解决方案3】:

    修复很简单,我需要使用 HTTPS,所以不用连接到 http://192.168.0.154:8733/... 我需要连接到https://192.168.0.154:8733/...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-10-26
      • 2023-03-11
      • 1970-01-01
      • 2010-11-04
      • 1970-01-01
      • 2011-10-05
      • 1970-01-01
      • 2020-03-11
      相关资源
      最近更新 更多