在對等網絡中模擬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端,其運行結果爲:

服務端

客戶端

 

此種模式若存在錯誤很難進行跟蹤。

 

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