在对等网络中模拟WCF单工消息交换模式

      在WCF中有三种消息交换模式(Message Exchange Pattern,MEP),包括单向通信模式、双工通信模式、请求-响应通信模式,其通过5种不同的信道来实现,其中不是每一种绑定都能支持这些信道,具体可以通过程序进行检测,可参考之前的检测结果。从其中可以看出对於单向通信模式的(IInputChannel和IOutputChannel)只有MsmqIntegrationBinding、NetMsmqBinding和NetPeerTcpBinding三种绑定在定制的基础上支持。本文介绍在VS2010 .NET 4.0.30319环境下,利用NetPeerTcpBinding这种定制的绑定模拟单向通信模式的实现。

     其中建立两个控制台应用程序,具体的结构如下图所示:

 

其中InputOutputServer是服务端,同时提供p2p名字解析的服务,负责侦听客户端请求,并用IInputChannel接收消息;InputOutputClient是客户端,通过IOutputChannel发送消息至服务端。其中需要额外引入几个程序库,图中已有标注。

       InputOutputServer端的Program.cs文件为:

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.Runtime.Serialization;
using System.ServiceModel.Security;
using System.Net.PeerToPeer;
using System.ServiceModel.PeerResolvers;

namespace InputOutputServer
{
    class Program
    {
        static void Main(string[] args)
        {
            //启动p2p对等网络的名称解析服务
            CustomPeerResolverService cprs = new CustomPeerResolverService();
            cprs.RefreshInterval = TimeSpan.FromSeconds(5);
            ServiceHost host = new ServiceHost(cprs);
            cprs.ControlShape = true;
            cprs.Open();
            host.Open(TimeSpan.MaxValue);            
            Console.WriteLine("p2p名称解析服务成功启动……,其地址为:"+host.Description.Endpoints[0].Address.ToString());

            //定义p2p对等网络的监听地址        
            Uri listenUri = new Uri("net.p2p://localhost/first");
            NetPeerTcpBinding binding = new NetPeerTcpBinding();
            binding.Resolver.Custom.Address = new EndpointAddress("net.tcp://localhost/Resolver");//定义p2p的名称解析服务所在的地址

            //定义获取p2p服务的绑定并设置
            NetTcpBinding tcpBinding = new NetTcpBinding();
            tcpBinding.Security.Mode = SecurityMode.None;    
            binding.Resolver.Custom.Binding = tcpBinding;

            //NetPeerTcpBinding默认是采用安全传输方式,设置其为不采用
            binding.Security.Mode = SecurityMode.None;

            //设置并开通监听端口
            IChannelListener<IInputChannel> listenChannel = binding.BuildChannelListener<IInputChannel>(listenUri);
            listenChannel.Open();            
            //建立消息接收通道
            IInputChannel channel = listenChannel.AcceptChannel(TimeSpan.MaxValue);            
            channel.Open();

            //接收消息
            Message rc = channel.Receive(TimeSpan.MaxValue);

            Console.WriteLine("接收到以下消息:");
            Console.WriteLine(rc);
            Console.WriteLine("按任意键结束……");
            Console.Read();
            host.Close();
            cprs.Close();

            

        }
    }
}


InputOutputServer的App.config文件为:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
    <services>
      <service name="System.ServiceModel.PeerResolvers.CustomPeerResolverService">
        <host>
          <baseAddresses>
            <add baseAddress="net.tcp://localhost/"/>
          </baseAddresses>
        </host>
        <endpoint address="Resolver" binding="netTcpBinding" bindingConfiguration="TcpConfig" contract="System.ServiceModel.PeerResolvers.IPeerResolverContract">          
        </endpoint>          
      </service>
    </services>

    <bindings>
      <netTcpBinding>
        <binding name="TcpConfig">
          <security mode="None"></security>
        </binding>
      </netTcpBinding>
    </bindings>
  </system.serviceModel>
</configuration>


 

InputOutputClient端的Program.cs文件为:

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


namespace InputOutputClient
{
    class Program
    {
        static void Main(string[] args)
        {
            NetPeerTcpBinding binding = new NetPeerTcpBinding();           
            binding.Security.Mode = SecurityMode.None;
            binding.Resolver.Custom.Address = new EndpointAddress("net.tcp://localhost/Resolver");
            NetTcpBinding tcpBinding = new NetTcpBinding();
            tcpBinding.Security.Mode = SecurityMode.None;
            binding.Resolver.Custom.Binding = tcpBinding;

            
            //建立输出的信道工厂
            IChannelFactory<IOutputChannel> outChannel = binding.BuildChannelFactory<IOutputChannel>();
            outChannel.Open();  
            //建立输出信道,必须指出信道目的服务的地址  
            IOutputChannel channel = outChannel.CreateChannel(new EndpointAddress("net.p2p://localhost/first"));
            channel.Open();
            //生成输出的消息并发出消息
            Message test = Message.CreateMessage(binding.MessageVersion, "test", "这是从客户端发送到net.p2p://localhost/first的消息");            
            channel.Send(test);

            test.Close(); 
            Console.WriteLine("信息已经发送至(net.p2p://localhost/first)。");
            Console.WriteLine("按任意键结束……");
                       
            Console.Read();
        }
    }
}


先运行InputOutputServer端,然后运行InputOutputClient端,其运行结果为:

服务端

客户端

 

此种模式若存在错误很难进行跟踪。

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章