当前位置: 代码迷 >> C# >> 一个容易的WCF双工,没有终结点在侦听.
  详细解决方案

一个容易的WCF双工,没有终结点在侦听.

热度:149   发布时间:2016-05-05 02:44:10.0
一个简单的WCF双工,没有终结点在侦听.....


 [ServiceContract(CallbackContract = typeof(ISomeCallbackContract))]
    public interface IService1
    {
        [OperationContract(IsOneWay = true)]   
        void DoSomething();
    }
    //用于回调的契约
    public interface ISomeCallbackContract
    {
        [OperationContract(IsOneWay = true)]
        void SomeCallbackMethod();
    }



 [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession, ConcurrencyMode = ConcurrencyMode.Reentrant)]
    public class Service1 : IService1
    {
        static List<ISomeCallbackContract> m_Callbacks = new List<ISomeCallbackContract>();
        public void DoSomething()
        {
            ISomeCallbackContract callback = OperationContext.Current.GetCallbackChannel<ISomeCallbackContract>();
            if (m_Callbacks.Contains(callback) == false)  
            {
                m_Callbacks.Add(callback);
            }
            Console.WriteLine("这句话是在服务端执行的");
            Thread.Sleep(5000);
            callback.SomeCallbackMethod();
        }
    }


<?xml version="1.0" encoding="utf-8"?>
<configuration>

  <system.web>
    <compilation debug="true" targetFramework="4.0" />
  </system.web>
  <system.serviceModel>
    <services>
      <service name="WcfService1.Service1" behaviorConfiguration="metadataExchange">
        <host>
          <baseAddresses>
            <add baseAddress="http://footdream.gotoip3.com"/> 
          </baseAddresses>
        </host>
        <endpoint address="Service1.svc" binding="wsDualHttpBinding" bindingConfiguration="NoneSecurity" contract="WcfService1.IService1"/>
      </service>
    </services>
    <bindings>
      <wsDualHttpBinding>
        <binding name="NoneSecurity" maxBufferPoolSize="12000000" maxReceivedMessageSize="12000000" useDefaultWebProxy="false">
          <readerQuotas maxStringContentLength="12000000" maxArrayLength="12000000"/>
          <security mode="None"/>
        </binding>
      </wsDualHttpBinding>
    </bindings>
    <behaviors>
      <serviceBehaviors>
        <behavior name="metadataExchange">
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
          <serviceMetadata httpGetEnabled="true"/>
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
 <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
        在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>
</configuration>

客户端:

public class CallBack : IService1Callback
{
    public void SomeCallbackMethod()
    {
       Console.WriteLine("kjkj");
    }
}


private void Button_Click(object sender, RoutedEventArgs e)
        {
            CallBack callback = new CallBack();
            InstanceContext context = new InstanceContext(callback);
            DuplexChannelFactory<IService1> channelFactory = new DuplexChannelFactory<IService1>(context, "WSDualHttpBinding_IService1");  
            IService1 service = channelFactory.CreateChannel();
            service.DoSomething();
            Console.Read();
        }


<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <wsDualHttpBinding>
                <binding name="WSDualHttpBinding_IService1">
                    <security mode="None" />
                </binding>
            </wsDualHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://footdream.gotoip3.com/Service1.svc"
                binding="wsDualHttpBinding" bindingConfiguration="WSDualHttpBinding_IService1"
                contract="aaa.IService1" name="WSDualHttpBinding_IService1" />
        </client>
    </system.serviceModel>
</configuration>

上面是一个简单的WCF双工示例,部署在IIS。在浏览器中能访问到服务,但是在客户端执行的时候,报错:
没有终结点在侦听可以接受消息的 http://footdream.gotoip3.com/Service1.svc。这通常是由于不正确的地址或者 SOAP 操作导致的。如果存在此情况,请参见 InnerException 以了解详....

请问,这是哪里出错了啊??
------解决思路----------------------
如果你在自己的电脑上浏览器地址栏里、手工访问 .svc  文件都看不到页面,那么就别跑什么客户端程序去测试了。
------解决思路----------------------
“在浏览器中能访问到服务”,是在客户端的机器的浏览器吗?

贴出来浏览器访问(成功)和客户端访问(调试)的截图。
------解决思路----------------------
我想你误解了wsDualHttpBinding双工的工作原理。

传统意义上的Http是‘单向’的,即客户请求一次,服务端回答一次,即服务端不能主动给客户发消息。
为了支持双工,wsDualHttpBinding工作方式在于建立了两个Http连接:
客户   ---------->    服务端(gotoip3.com)
客户  <----------    服务端(gotoip3.com)

其中,第二个连接由服务端连接到客户端以便提供回调服务。这就要求服务端必须能够主动连接到客户端,因此客户端必须有公开的网址。

你帖子中WCF客户端<client>的配置,客户网址用的是"http://footdream.gotoip3.com/Service1.svc",我估计这是一个错误。你应该用客户的实际地址,而不是服务端的地址。如果gotoip3.com不是客户拥有的地址,自然没有办法绑定到别人家的端点上(报错:没有终结点在侦听可以接受消息的http://footdream.gotoip3.com/Service1.svc)。

因此改正方法就是客户提供正确的回调端点,并保证服务端可以连接到客户端点

另外,你可以看到wsDualHttpBinding的限制很大,客户要有公网地址,客户不能被防火墙阻断。因此,除非在企业局域网等可控环境,一般wsDualHttpBinding是不合适的。建议你放弃wsDualHttpBinding。

如果不要双工的话只用HttpBinding(可扩展性很好,客户可以定时向服务段要最新通知);
如果一定要回调,可以用net.tcp(比较高效,但不是Http协议);
如果一定要回调,而且只能走Http协议,可以使用XMPP/BOSH,或仿照SliverLight的PollingDuplexHttpBinding(效率不高)。


wsDualHttpBinding参考:
https://msdn.microsoft.com/zh-cn/library/system.servicemodel.wsdualhttpbinding%28v=vs.100%29.aspx







------解决思路----------------------
IIS本身可以支持tcp.net绑定。

但是,
有可能某些网站提供商只允许Http流量,你寄放的IIS收不到net.tcp。
有可能某些客户的防火墙比较严格,只允许外出网页访问,不允许其他诸如聊天协议,net.tcp等等。
------解决思路----------------------
引用:
Quote: 引用:


另外,你可以看到wsDualHttpBinding的限制很大,客户要有公网地址,客户不能被防火墙阻断。因此,除非在企业局域网等可控环境,一般wsDualHttpBinding是不合适的。建议你放弃wsDualHttpBinding。

由于IIS是支持HTTP协议的,如果使用net.tcp的话,服务就不寄宿在IIS中,是吧?


你不是连客户端访问服务器这种任何编程方式都起码第一时间应该做到的效果都看不到吗?怎么一下子又跳到net.tcp上了?
------解决思路----------------------
所谓服务寄宿在xxx中,是说被什么进程启动、必须通过它来初始化而已。你通过IIS最初访问asp.net程序,都是可以叫做“寄宿在IIS中”。这跟net.tcp本身不依赖于IIS而是依赖HTTP.sys等,没有很大的关系,只是部署问题而已。纠结它“寄宿在哪里”解决不了技术问题。
------解决思路----------------------
而是依赖HTTP.sys等   -->   而是依赖HTTP.sys还是TCPIP.sys等系统底层
------解决思路----------------------


之前就说了,IIS不支持nettcp

只有Win服务与Exe支持,你呀你。。。。。。
------解决思路----------------------
引用:
Windows服务支持NetTcpBinding吗?我打算把WCF寄宿在Windows服务

楼主兄弟,这问题你连搞几天了,现在你总算想通了,不要将时间浪费在虚拟主机上了,想要双工,你最好选云主机、独立服务器都行,有了这,别说windows服务,微软提供的所有托管方式你都可以实现了。
------解决思路----------------------
引用:
Windows服务支持NetTcpBinding吗?我打算把WCF寄宿在Windows服务


你最好先把你的问题集中一点考虑。尤其不要刚学一半,就自满地要自己发明什么。

首先你要找一个教程,确保它本身确实是实现过双向通讯的(而不是瞎抄别人的文章的),然后按照它的开发环境、部署方法来练习。

你在这里一会儿功夫把自己的根本以来的东西都推翻了,哪一个教程会会这样写呢?看来你是没有耐心去都完整任何教程的。


------解决思路----------------------
你所贴出的最后一个图中的配置是乱写的。你应该知道自己乱改了哪些东西,然后比较实在地说明你贴的是抄哪些教程的,其中只有哪些东西是你自己想出来而改动过的。

不要贴一大堆抄来的代码,翻来复去地问同样的问题。如果这样翻来覆去地,那么就算是你改为 net.tcp 协议,恐怕也好不了多少啊。了解其中几十分之一的代码,就能了解问题的实质。而你总是懒得减少问题,总是喜欢贴过多的代码。
------解决思路----------------------
嗯,这么说吧。如果你打算改 net.tcp,那么把帖子结了,并且把你为了学习而抄来的代码也彻底删除了。然后重新找一个教程,仔细按照步骤来实际操做。

不要像现在这样,刚弄到一半,又想改学另一个东西了。虽然你以为代码差不多,但是其实没有你还没有凭自己的本事就分身地能够综合不同教程上的案例的能力。所以不要这样“跳跃”。

你贴的代码,看得出,基本上全都是抄来的,你只是改了配置。而你偏偏不把所提的问题的焦点聚集在你唯一自己能够做主的配置上,已经可见得到你是怎么学习编程的了。
  相关解决方案