首頁  >  文章  >  後端開發  >  對wcf的理解--實現計算器功能

對wcf的理解--實現計算器功能

零下一度
零下一度原創
2017-06-24 09:36:321829瀏覽

WCF本質上提供一個跨進程、跨機器以致跨網絡的服務調用,本示例中主要實現了計算器的功能,大部分的函數來自網上別人的帖子,這叫站在巨人的肩膀上,O(∩_∩)O哈哈~,但是為了加深自己的對wcf的理解,因此決定自己在寫個類似的demo,把寫demo中遇到的問題展現出來,我相信對於初識wcf的程序員了來說,也會遇到各種問題。好了步入正題。

WCF 分為四個部分1、契約(Interface)2、服務契約(Service)3、WCF 宿主程式(控制台或IIS) 4、客戶端(Client)

本人在寫wcf的時候喜歡將四個部分分別拆分成不同的類別庫來管理。

1、契約 

     契約是對外開放的接口,暴露給客戶端的函數名稱首先,新建一個wcf服務庫,名稱為Interface,如圖所示:

刪除程式中預設的檔案(App.config,IService1.cs,Service1.cs),新建ICalculator

namespace Interface
{
    [ServiceContract(Name = "CalculatorService", Namespace = "")]public interface ICalculator
    {
        [OperationContract]double Add(double x, double y);

        [OperationContract]double Subtract(double x, double y);

        [OperationContract]double Multiply(double x, double y);

        [OperationContract]double Divide(double x, double y);

    }
}

2、新建服務契約,其實就是實作契約的類,新增"新建專案"->WCF->"WCF服務庫" (如第一步新建契約是一樣的步驟),類別庫的名稱為Service,

對wcf的理解--實現計算器功能

namespace Service
{
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]public class CalculatorService : ICalculator
    {public double Add(double x, double y)
        {return x + y;
        }public double Subtract(double x, double y)
        {return x - y;
        }public double Multiply(double x, double y)
        {return x * y;
        }public double Divide(double x, double y)
        {return x / y;
        }
    }

3、新建WCF宿主程序,WCF的契約和服務契約都已經建完,但是還需要一個程式來承載這些介面供外部程式調用,因此稱之為宿主程序,宿主程式可以部署在IIS上,也可以用控制台程式運行方便調試,下面我就介紹用控制台程式作為宿主程式。在解決方案的名稱右鍵添加"控制台程式" 名稱為Hosting ,添加對Interface和Service的引用

#實現wcf對外開放有兩種方式,一種方式是配置文件,將所有的WCF信息都寫到設定檔中

第一種:WCF的相關資訊寫到設定檔(App.config)中 

<?xml  version="1.0" encoding="utf-8"?>
<configuration>
  <startup>
    <supportedruntime></supportedruntime>
  </startup>
  <system.servicemodel>
    <services>
      <service>
        <endpoint>          
        </endpoint>
        <endpoint>
        </endpoint>
        <endpoint></endpoint>
        <endpoint></endpoint>
        <host>
          <baseaddresses>
            <add></add>
            <add></add>
          </baseaddresses>
        </host>
      </service>
    </services>
    <behaviors>
      <servicebehaviors>
        <behavior>
          <servicemetadata></servicemetadata>
          <servicedebug></servicedebug>
        </behavior>
      </servicebehaviors>
    </behaviors>
  </system.servicemodel>
</configuration>

 

 

Main方法的主要程式碼如下,

    public class Program
    {internal static ServiceHost host = null;static void Main(string[] args)
        {using (ServiceHost host = new ServiceHost(typeof(CalculatorService)))
            {

                host.Opened += delegate{
                    Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
                };
                host.Open();
                Console.ReadLine();
            }
        }
    }

執行控制台程序,如下圖所示:

第二種:寫一個WCFHelper類,加入幫助類的時候,一定引用System.Runtime.Serialization ,並且刪除App.config 對wcf的配置,否則會報錯代碼如下:

 public static class WCFHelper
    {public static string IP { get; set; }public static int Port { get; set; }static WCFHelper()
        {try{
                IP = System.Environment.MachineName;// ConfigurationManager.AppSettings["ServiceIP"];//                Port = int.Parse(ConfigurationManager.AppSettings["ServicePort"]);
            }catch{

            }

            EndpointAddress.Add(BindingProtocol.Http, "http://{0}:{1}/{2}/{3}");
            EndpointAddress.Add(BindingProtocol.NetTcp, "net.tcp://{0}:{1}/{2}/{3}");//EndpointAddress.Add(BindingProtocol.NetMsmq, "net.msmq://{0}:{1}/" + schema + "/{2}");//EndpointAddress.Add(BindingProtocol.NetPipe, "net.pipe://{0}:{1}/" + schema + "/{2}");try{
                httpBinding = new BasicHttpBinding();
                httpBinding.MaxBufferSize = 200065536;
                httpBinding.MaxReceivedMessageSize = 200065536;
                httpBinding.CloseTimeout = new TimeSpan(0, 10, 0);
                httpBinding.OpenTimeout = new TimeSpan(0, 10, 0);
                httpBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
                httpBinding.SendTimeout = new TimeSpan(0, 1, 0);

                httpBinding.Security.Mode = BasicHttpSecurityMode.None;

                httpBinding.ReaderQuotas.MaxDepth = 64;
                httpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
                httpBinding.ReaderQuotas.MaxArrayLength = 16384;
                httpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
                httpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;
            }catch{
                httpBinding = new BasicHttpBinding();
            }try{
                tcpBinding = new NetTcpBinding();
                tcpBinding.CloseTimeout = new TimeSpan(0, 1, 0);
                tcpBinding.OpenTimeout = new TimeSpan(0, 1, 0);
                tcpBinding.ReceiveTimeout = new TimeSpan(0, 10, 0);
                tcpBinding.SendTimeout = new TimeSpan(0, 1, 0);
                tcpBinding.TransactionFlow = false;
                tcpBinding.TransferMode = TransferMode.Buffered;
                tcpBinding.TransactionProtocol = TransactionProtocol.OleTransactions;
                tcpBinding.HostNameComparisonMode = HostNameComparisonMode.StrongWildcard;
                tcpBinding.ListenBacklog = 100000;
                tcpBinding.MaxBufferPoolSize = 524288;
                tcpBinding.MaxBufferSize = 200065536;
                tcpBinding.MaxConnections = 2000;
                tcpBinding.MaxReceivedMessageSize = 200065536;
                tcpBinding.PortSharingEnabled = true;

                tcpBinding.Security.Mode = SecurityMode.None;

                tcpBinding.ReaderQuotas.MaxDepth = 64;
                tcpBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
                tcpBinding.ReaderQuotas.MaxArrayLength = 163840000;
                tcpBinding.ReaderQuotas.MaxBytesPerRead = 4096;
                tcpBinding.ReaderQuotas.MaxNameTableCharCount = 16384;

                tcpBinding.ReliableSession.Ordered = true;
                tcpBinding.ReliableSession.InactivityTimeout = new TimeSpan(0, 10, 0);
                tcpBinding.ReliableSession.Enabled = false;
            }catch{
                tcpBinding = new NetTcpBinding();
            }
        }private static BasicHttpBinding httpBinding;public static BasicHttpBinding HttpBinding
        {get{return httpBinding;
            }
        }private static NetTcpBinding tcpBinding;public static NetTcpBinding TcpBinding
        {get{return tcpBinding;
            }
        }public static EndpointAddress GetEndpointAddress(string ip, int port, string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];
            address = string.Format(address, ip, port, serviceSchema, serviceName);return new EndpointAddress(address);
        }public static EndpointAddress GetEndpointAddress(string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];
            address = string.Format(address, IP, Port, serviceSchema, serviceName);return new EndpointAddress(address);
        }public static Uri GetBaseAddress(string ip, int port, string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];

            address = string.Format(address, ip, port + 1, serviceSchema, serviceName);return new Uri(address);
        }public static Uri GetBaseAddress(string serviceSchema, string serviceName, BindingProtocol protocol)
        {string address = EndpointAddress[protocol];

            address = string.Format(address, IP, Port + 1, serviceSchema, serviceName);return new Uri(address);
        }private readonly static Dictionary<bindingprotocol> EndpointAddress = new Dictionary<bindingprotocol>();public enum BindingProtocol
        {
            Http = 1,
            NetTcp = 2,//NetPipe = 3,//NetMsmq = 4        }
    }</bindingprotocol></bindingprotocol>

將宿主程式中的main方法改成如下:

    static void Main(string[] args)
        {
            WCFHelper.IP = "127.0.0.10";
            WCFHelper.Port = 9999;

            Uri httpUri = WCFHelper.GetBaseAddress(WCFHelper.IP, WCFHelper.Port, "Calculator", "Inspect", WCFHelper.BindingProtocol.Http);using (ServiceHost host = new ServiceHost(typeof(CalculatorService), httpUri))
            {
                host.AddServiceEndpoint(typeof(ICalculator), WCFHelper.TcpBinding, WCFHelper.GetEndpointAddress(WCFHelper.IP, WCFHelper.Port, "Calculator", "InspectService", WCFHelper.BindingProtocol.NetTcp).Uri.AbsoluteUri);
                ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();#if DEBUGbehavior.HttpGetEnabled = true;#elsebehavior.HttpGetEnabled = false;#endifhost.Description.Behaviors.Add(behavior);
                host.Opened += delegate{
                    Console.WriteLine("CalculaorService已经启动,按任意键终止服务!");
                };
                host.Open();

                Console.ReadLine();
            }
}

 

 

4、宿主程式建完了,WCF的所有鍥約已經對外可以存取了,那現在需要建立Client 去呼叫wcf程式了,

首先,編譯宿主程式Host,找到bin/debug/ Host.exe 右鍵管理員打開,如果如下圖證明服務已經於寧

其次,在解決方案名稱->右鍵新增Winform程式 新建WinForm 程式,新增"服務引用"

新增服務引用(此引用方式,是以"3、新增宿主程式" ->"第二種WCF幫助類別的方式")

點選「前往」 系統發現WCF服務,如下圖:

 

點擊確定,就成功的將wcf的引用了,下面開始呼叫WCF的程式了,例如呼叫Add方法,程式碼如下:

 ServiceReference1.CalculatorServiceClient client = new ServiceReference1.CalculatorServiceClient();
            textBox3.Text = client.Add(double.Parse(textBox1.Text), double.Parse(textBox2.Text)).ToString();

到此為止,wcf程式已經完成的跑通了,記得調試的時候已經把宿主程式和client程式同時運行。

如果閒麻煩,vs 支援同時啟動多個項目,可以同時把client 和host同時啟動

 

#

以上是對wcf的理解--實現計算器功能的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn