【问题标题】:Problem with configuring and starting WCF service配置和启动 WCF 服务的问题
【发布时间】:2011-10-02 17:39:49
【问题描述】:

我在配置和启动 WCF 服务时遇到问题。 在我的应用程序中有一个启动服务的方法。像这样的

void Start(string protocol, string address, string port)
{
    host = new ServiceHost(_myService,
        new Uri(String.Format("{0}://{1}{2}/Sample", protocol, address, port)));
    //...Some configuration (bindings, behaviors, etc.)
    host.Open();
}

让我的电脑有一个 IP 192.168.0.1。当我传递值为 '192.168.0.2' 的 'address' 参数时,发生错误

"A TCP error (10049: The requested address is not valid in its context.)
 occurred while listening on IP Endpoint=192.168.0.2:1234"

没错,因为它不是我的 IP。但在那之后,如果我传递正确的值(我的真实 IP),我会收到关于 IP 192.168.0.2 的相同错误!所以我无法在不重新启动应用程序的情况下重新配置和重新启动服务器。

为什么会这样?我怎样才能避免这种行为?

【问题讨论】:

    标签: c# .net wcf configuration


    【解决方案1】:

    看起来 WCF 在 ExclusiveTCPTransportManager 类中缓存了一个套接字对象。

    这对我来说似乎是一个很好的解决方案:

    public static class WCFBugWorkaround
    {
        public static bool IsConnectionPossible(this ServiceHost host)
        {
            try
            {
                foreach (var baseAddress in host.BaseAddresses)
                {
                    IPAddress[] ipAddresses = Dns.GetHostAddresses(baseAddress.DnsSafeHost);
                    IPAddress ipAddr = ipAddresses.Where(e => e.AddressFamily == AddressFamily.InterNetwork).FirstOrDefault();
    
                    if (ipAddr == null)
                    {
                        return false;
                    }
    
                    using (Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp))
                    {
                        System.Net.IPEndPoint localEP = new IPEndPoint(ipAddr, baseAddress.Port);
                        s.Bind(localEP);
                    }
                }
            }
            catch (Exception ex)
            {
                return false;
            }
    
            return true;
        }
    }
    
    ServiceHost host = ...;
    
    ...
    
    if (host.IsConnectionPossible())
    {
        host.Open();
    }
    

    感谢 Francheska 为我指明了正确的方向 :)

    【讨论】:

      【解决方案2】:

      我无法从您的问题中看到您如何添加正确的端点,但我怀疑您正在尝试修改端点地址。使用 WCF 服务,您无法在调用后更改端点地址

      host.Open();
      

      因为此时服务(如果您没有错误)启动并接受来自指定地址和端口号的客户端的请求。

      如果您希望在新地址托管服务,则需要使用正确的端点地址创建一个新的 ServiceHost 对象(并丢弃旧的)。

      编辑:

      在玩弄了您发布的示例解决方案后,我找到了该问题的解决方案。我认为出了点问题,因为您在两次尝试中都使用了相同的端口号(在我下载的示例解决方案中,您没有指定这个,所以端口默认为 808)。如果您按如下方式更改代码以在第二次尝试的基地址中指定不同的端口号,您遇到的错误就会消失:

       try
              {
                  var host2 = CreateServiceHost("localhost:5432", serviceImpl);
      
                  Console.WriteLine("#2, config: " + host2.BaseAddresses.First().ToString());
      
                  host2.Open();
              }
              catch (Exception ex)
              {
                  Console.WriteLine(ex.Message);
              }
      

      WCF 本身下面似乎有一些错误,可能在套接字级别,在第一个错误 IP 不正确后,端口仍然不可用。

      我做了一个快速的谷歌和found this article,其中有人在关闭套接字后重用端口时遇到延迟。如果您总是需要使用相同的端口号,也许您可​​以等待一段时间让端口再次空闲,然后再尝试创建服务主机。

      【讨论】:

      • 感谢您的回复!在错误的 IP 启动失败后再次调用方法“开始”时遇到问题。问题是我每次都创建一个新的 ServiceHost 实例,如您所见。如果之前尝试启动服务失败,使用新实例和新配置的新服务也会失败,并且错误将与之前尝试相同(包括之前的 IP,即使我提供了新的正确 IP)
      • 它会从你的 app.config 文件中提取以前的 IP 地址吗?当您从应用程序创建服务主机时,它会自动选择您在 app.config 文件中为主机应用程序配置的任何端点。
      • 不,不可能…… app.config中根本没有服务配置数据。如果我使用真实 IP(例如 127.0.0.1,然后是 192.168.0.1,然后是我的 Internet IP)重新启动服务,一切正常。但是尝试使用不正确的 IP 后重新启动总是失败
      • 有趣。即使您将 host.open() 的代码包装在 try-catch 中,并在捕获 IP 地址错误时关闭/处置服务,也会发生这种情况吗?您可以发布您正在使用的代码,以便我自己尝试一下吗? :)
      • 抱歉耽搁了。我已经为这个问题创建了一个测试项目。 filefactory.com/file/cc893b3/n/ServiceConfigTest.zip
      猜你喜欢
      • 1970-01-01
      • 2011-02-04
      • 1970-01-01
      • 1970-01-01
      • 2011-04-15
      • 1970-01-01
      • 2012-12-06
      • 2020-01-09
      • 1970-01-01
      相关资源
      最近更新 更多