【问题标题】:WCF port not listeningWCF 端口未侦听
【发布时间】:2017-04-12 17:42:54
【问题描述】:

更新

该服务正在运行,并且在任务管理器中有一个 pid,但是当我运行 netstat -ano | find pid# 时没有返回任何内容 - 端口没有在监听。

另外,如果我运行netstat -ap tcp,则端口未列出。

我真的不知道如何解决这个问题。总而言之,您不必阅读我之前的帖子:

  • 我的 WCF 服务在 localhost 下完美运行(即服务和客户端在同一台服务器上)
  • 当我将服务发布到生产服务器时,服务安装正常,但 8523 端口不监听
  • 我查看了几篇类似的帖子,但没有一个适合我
  • 这是我尝试的第一个 WCF 项目,所以我已经用尽了我的知识,我无法在 Internet 上找到更多示例来尝试
  • 在这一点上,我将非常感谢任何指点

环境

  • 开发:Windows 7
  • Visual Studio:2015 年
  • 生产服务器:Windows Server 2008 R2 数据中心
  • IIS 版本 7.5.7600.16385

简介

我已经研究这个问题几天了,虽然我在 Stack Overflow 上发现了许多类似的问题,但这些问题都没有解决我的问题;因此,我不认为这是重复的,如果有人像我一样尝试遵循引用的 Microsoft 教程,这将特别有帮助

问题详情

我在https://msdn.microsoft.com/en-us/library/ff649818.aspx 关注了这篇 Microsoft 文章“如何:使用 TCP 在 Windows 服务中托管 WCF”。

创建解决方案后,它可以在 Visual Studio localhost 环境中的我的开发机器上完美运行。本教程建议您创建一个测试客户端来访问 WCF 解决方案,并且该测试客户端可以成功运行

当我在生产机器 (Windows Server 2008) 中发布 WCF 服务和 Windows 服务时,它会再次安装而没有错误。以下是我遵循的步骤:

IIS 设置

  • 将 net.tcp 添加到启用的协议中

  • 激活“Windows Communication Foundation 非 HTTP 激活”

  • 将 net.tcp 的绑定更改为 8532

  • 确保“Net.Tcp 侦听器适配器”正在运行

在防火墙中打开 8532 端口

浏览到WindowsService1.exe所在项目的bin目录,以管理员身份运行该exe

以管理员身份打开命令提示符并运行 Installutil WindowsService1.exe

Localhost(Visual Studio 中的开发环境)和生产环境的区别

本地 WCF 系统和生产系统之间的唯一变化是我将 app.conf 中的 baseAddress 从

  • "net.tcp://localhost:8523/CustomWCFService"

  • “net.tcp://10.2.1.1:8523/CustomWCFService”

这里是部署的 app.conf

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="MyCustomServiceLib.CustomServiceLib">
        <endpoint address="" binding="netTcpBinding" bindingConfiguration=""
          contract="MyCustomServiceLib.ICustomServiceLib">
          <identity>
            <dns value="localhost" />
          </identity>
        </endpoint>
        <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration=""
          contract="IMetadataExchange" />
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://10.2.1.1:8523/CustomWCF" />
          </baseAddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="">
          <serviceMetadata httpGetEnabled="false" httpsGetEnabled="false" />
          <serviceDebug includeExceptionDetailInFaults="false" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

添加服务参考

当我尝试在将使用 WCF 服务的应用程序中添加服务引用时。我收到此错误:

从地址下载元数据时出错。请 验证您输入的地址是否有效

当我点击“详细信息”时,我看到了这个:

URI 前缀无法识别。元数据包含一个引用 无法解决:'net.tcp://10.2.1.1:8523/CustomWCF'。不能 连接到 net.tcp://10.2.1.1:8523/CustomWCF。连接尝试 持续了 00:00:01.0312368 的时间跨度。 TCP 错误代码 10061:否 可以建立连接,因为目标机器主动拒绝 它是 10.2.1.1:8523。无法建立连接,因为目标 机器主动拒绝它 10.2.1.1:8523 如果服务定义在 当前解决方案,尝试构建解决方案并添加服务 再次参考。

我尝试过的

在论坛上提出的许多其他 WCF 问题似乎与让服务在 localhost 中运行有关,这不适用于我,因为我创建的解决方案在开发环境中完美运行。

一些答案​​建议在项目中启用 tcp 端口共享,但是当我尝试在我的解决方案中添加此代码时,我收到一条错误消息“不允许”。

其他问题建议该url必须在生产服务器上注册但没有效果。

在尝试了我能找到的所有论坛建议并尝试纠正我认为错误的所有内容后,我仍然没有运气。

任何建议或指点将不胜感激

【问题讨论】:

  • 我忘记提到的一个重要点是当我运行 netstat -ona | find "8523" 没有返回任何内容。如果端口未在侦听,则服务将无法工作

标签: c# .net wcf tcp


【解决方案1】:

过去我没有让 WCF 与配置文件很好地配合使用。我一直在代码中创建绑定。

这个gist 确实有效。

重要的部分是NetTcpBinding

 netTcpBinding = new NetTcpBinding
                            {
                                MaxReceivedMessageSize = int.MaxValue,
                                MaxBufferPoolSize = int.MaxValue,
                                Security = new NetTcpSecurity
                                           {
                                               Mode = SecurityMode.None,
                                               Transport = new TcpTransportSecurity()
                                           }
                            };

另外,我不会指定 IP,而是让 WCF 将其绑定到机器上的每个 IP 地址。

serviceHost.AddServiceEndpoint(typeof(ITestService), netTcpBinding, string.Format("{1}://0.0.0.0:{0}/", port, "net.tcp"));

这不会阻止您输入特定的 IP,我只是通常不会。

如果你想在 IIS 中运行它,你必须做更多的工作。 IIS 并不真正希望您托管不受 http 绑定的 WCF 服务器。

在创建 ServiceHost 后你还需要做一些额外的工作

 var serviceBehavior = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();

if (serviceBehavior == null) return;

serviceBehavior.HttpGetEnabled = false;
serviceBehavior.HttpsGetEnabled = false;

【讨论】:

  • 同意,WCF 和配置文件对我来说也很不稳定,所以我现在为 WCF 服务避免使用它们。
  • 大卫:非常感谢你的新方向。这是非常赞赏。我会将您的建议添加到我的代码中并试一试
  • David:我使用您建议的代码更改创建了一个新的 WCF 库服务,并且一切构建都没有错误。但是,我确实有一个问题。为了添加服务引用以从另一台机器连接到我们的新 WCF 库,我们仍然需要一个 Windows 服务来托管 WCF 服务库,对吗?构建 Windows 服务的一部分是为其提供来自 WCF 库的 app.conf 副本。我们现在库中没有 app.conf 文件,因为它已被您的附加编程代码替换。没有这个 app.conf 文件,Windows 服务如何工作?
  • @DrakesDR 对于 WCF,您可以将它托管在您想要的任何 exe 中。这完全取决于您的应用程序。窗口服务是一种很好的消费方式。过去,我有 1 个包含所有 WCF 代码的库。我有一个客户端和一个服务器。然后我将创建一个与服务器对话的新客户端。有一个 BIG WCF 陷阱会让你大吃一惊。您需要确保始终使用相同的模型。如果它们不同,您将收到序列化错误,并且很多时候 WCF 会吞下这些错误。
【解决方案2】:

我添加了这篇文章来详细说明将 David Basarab 建议更改添加到我的 WCF 服务库项目的结果。再次非常感谢大卫的帖子,但不幸的是我无法让它工作。事实上,它甚至没有在 Visual Studio 的 localhost 下运行。大卫提到它对他有用,所以我可能在某个地方犯了错误。希望我在这里提供的细节会产生一些额外的指针,指出我做错了什么,或者帮助其他尝试大卫方法的人。在创建解决方案时,我尝试保留 Visual Studio 默认值,但 David 的更改除外。

服务引用错误

当我尝试在 Windows 服务和实际 WCF 服务库所在的同一台机器上的测试客户端中添加服务引用时,我收到了以下错误:

The URI prefix is not recognized. Metadata contains a reference that cannot be resolved: 'net.tcp://localhost:8523/Service1'. Could not connect to net.tcp://localhost:8523/Service1. The connection attempt lasted for a time span of 00:00:02.0028015. TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8523. No connection could be made because the target machine actively refused it 127.0.0.1:8523 If the service is defined in the current solution, try building the solution and adding the service reference again.

WCF 库代码

IService1.cs 单元

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace CustomServiceLibrary
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "IService1" in both code and config file together.
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);

        // TODO: Add your service operations here
    }

    // Use a data contract as illustrated in the sample below to add composite types to service operations.
    // You can add XSD files into the project. After building the project, you can directly use the data types defined there, with the namespace "CustomServiceLibrary.ContractType".
    [DataContract]
    public class CompositeType
    {
        bool boolValue = true;
        string stringValue = "Hello ";

        [DataMember]
        public bool BoolValue
        {
            get { return boolValue; }
            set { boolValue = value; }
        }

        [DataMember]
        public string StringValue
        {
            get { return stringValue; }
            set { stringValue = value; }
        }
    }
}

Service1.cs 代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;

namespace CustomServiceLibrary
{
    // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in both code and config file together.
    public class Service1 : IService1
    {
        public string GetData(int value)
        {
            return string.Format("You entered: {0}", value);
        }

        public CompositeType GetDataUsingDataContract(CompositeType composite)
        {
            if (composite == null)
            {
                throw new ArgumentNullException("composite");
            }
            if (composite.BoolValue)
            {
                composite.StringValue += "Suffix";
            }
            return composite;
        }
    }
}

Server.cs 类代码

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace CustomServiceLibrary
{
    class Server
    {
        private readonly ushort port;
        private readonly Service1 Service1;
        private NetTcpBinding netTcpBinding;
        private ServiceHost serviceHost;

        public Server(ushort port)
        {
            this.port = port;
            Service1 = new Service1();
        }

        public void Start()
        {
            try
            {
                CreateServiceHost();

                CreateBinding();

                AddEndpoint();

                serviceHost.Open();

                Console.WriteLine("Service has been opended");

                ConfigureHTTP();
            }
            catch (Exception ex)
            {
                Console.WriteLine($"ERROR      := {ex.Message}");
                Console.WriteLine($"StackTrace := {ex.StackTrace}");
            }
        }

        private void AddEndpoint()
        {
            serviceHost.AddServiceEndpoint(typeof(IService1), netTcpBinding, string.Format("{1}://0.0.0.0:{0}/", port, "net.tcp"));
        }

        private void ConfigureHTTP()
        {
            var serviceBehavior = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();

            if (serviceBehavior == null) return;

            serviceBehavior.HttpGetEnabled = false;
            serviceBehavior.HttpsGetEnabled = false;
        }

        private void CreateBinding()
        {
            netTcpBinding = new NetTcpBinding
            {
                MaxReceivedMessageSize = int.MaxValue,
                MaxBufferPoolSize = int.MaxValue,
                Security = new NetTcpSecurity
                {
                    Mode = SecurityMode.None,
                    Transport = new TcpTransportSecurity()
                }
            };
        }

        private void CreateServiceHost()
        {
            serviceHost = new ServiceHost(Service1);
        }
    }
}

总结

除了我添加到项目中的 David 的更改之外,我所做的一切都与我之前使用 App.conf 配置为部署所做的相同。我只是按照 Microsoft 文章“如何:使用 TCP 在 Windows 服务中托管 WCF”中的说明进行操作,地址为 https://msdn.microsoft.com/en-us/library/ff649818.aspx

【讨论】:

    猜你喜欢
    • 2021-10-10
    • 1970-01-01
    • 1970-01-01
    • 2017-09-23
    • 1970-01-01
    • 2017-04-25
    • 2014-08-03
    • 1970-01-01
    • 2017-06-04
    相关资源
    最近更新 更多