C# WCF服務入門

来源:http://www.cnblogs.com/onegarden/archive/2017/07/07/7134426.html
-Advertisement-
Play Games

之前在公司用的服務端是wcf寫的,但是沒有深入研究,最近找工作,面試的時候好多人看到這個總提問,這裡做個複習 就用微軟官方上的例子,搭一個簡單的wcf服務,分6步 1 定義服務協定也就是契約,其實就是定義一個服務介面,這玩意後邊是公開客戶端用的,然後也告訴後邊承載程式應該如何載入服務 主要涉及兩個特 ...


之前在公司用的服務端是wcf寫的,但是沒有深入研究,最近找工作,面試的時候好多人看到這個總提問,這裡做個複習

就用微軟官方上的例子,搭一個簡單的wcf服務,分6步

1 定義服務協定也就是契約,其實就是定義一個服務介面,這玩意後邊是公開客戶端用的,然後也告訴後邊承載程式應該如何載入服務

   主要涉及兩個特性:一個是ServiceContract(介面的特性,定義這個是服務契約,裡邊又一些設置參數可以設置一下),OperationContract設置介面的方法的,如果不設置,方法就不會唄公開

  這裡是直接新建的wcf的服務程式,vs自動給生成了一個介面,就直接在這個裡邊添加了幾個計算的介面函數了

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

namespace GettingStartedLib
{

    // 註意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼和配置文件中的介面名“IService1”。
    //協定
    [ServiceContract(//CallbackContract =typeof(ICallBack),//雙工時的返回協定
        ConfigurationName = "Calculator",//配置文件重的服務名
        Name = "ICalculator",//webservice描述文件重的portType名
        Namespace ="http://SampleWcfTest",//webservice描述文件重的portType命名空間
        ProtectionLevel =System.Net.Security.ProtectionLevel.EncryptAndSign,//保護等級
        SessionMode =SessionMode.Allowed)]//設置會話的支持模式
    public interface ICalculator
    {

        [OperationContract]
        string GetData(int value);

        [OperationContract]
        CompositeType GetDataUsingDataContract(CompositeType composite);
        //定義方法的操作,帶了該特性才會被公佈
        [OperationContract]
        double Add(double n1, double n2);
        [OperationContract]
        double Subtract(double n1, double n2);
        [OperationContract]
        double Multiply(double n1, double n2);
        [OperationContract]
        double Divide(double n1, double n2);

        // TODO: 在此添加您的服務操作
    }
    public interface ICallBack
    {
        [OperationContract(IsOneWay = true)]
        void Reply(string responseToGreeting);
    }

    // 使用下麵示例中說明的數據約定將複合類型添加到服務操作。
    [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; }
        }
    }
}

2 實現上邊的介面,vs自動生成了svc文件和對應的svc.cs文件,直接雙擊就是對應的實現類了,吧介面實現就好了,這個svc文件右鍵用文本編輯器打開可以進行編輯,如果後邊用IIS載入的時候需要修改裡邊的東西

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

namespace GettingStartedLib
{
    // 註意: 使用“重構”菜單上的“重命名”命令,可以同時更改代碼、svc 和配置文件中的類名“Service1”。
    // 註意: 為了啟動 WCF 測試客戶端以測試此服務,請在解決方案資源管理器中選擇 Service1.svc 或 Service1.svc.cs,然後開始調試。
    public class Calculator : ICalculator
    {
        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;
        }
        public double Add(double n1, double n2)
        {
            double result = n1 + n2;
            Console.WriteLine("Received Add({0},{1})", n1, n2);
            // Code added to write output to the console window.
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Subtract(double n1, double n2)
        {
            double result = n1 - n2;
            Console.WriteLine("Received Subtract({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Multiply(double n1, double n2)
        {
            double result = n1 * n2;
            Console.WriteLine("Received Multiply({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }

        public double Divide(double n1, double n2)
        {
            double result = n1 / n2;
            Console.WriteLine("Received Divide({0},{1})", n1, n2);
            Console.WriteLine("Return: {0}", result);
            return result;
        }
    }
}

3 承載服務,承載服務有幾種方式,同時又設計到協議的綁定問題,

  綁定分類:BasicHttpBinding  最基礎的http綁定,
        NetTcpbingding  TCP的  

        NetNamePipeBinding  IPC,也就是進程間通信,沒用過。。

        WSHttpBinding  這個是特殊的http/Https協議 加了其他東西的

        NetMsmqBindiing,這個是消息隊列,我沒用過,這玩意好像需要額外裝微軟的消息隊列才可以用

  這裡我基本就用wshttpbinding來實現,

  承載方式:1)用控制台程式,直接用servicehost來承載服務,自己構造終結點:

            //服務的地址
            Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
            //承載服務的宿主
            ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress);

            try
            {
                selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                selfHost.Description.Behaviors.Add(smb);
                selfHost.Open();
                Console.WriteLine("The service is ready.");
                Console.WriteLine("input<exit> to terminate service.");
                Console.WriteLine();
                while ("exit" == Console.ReadLine())
                {
                    selfHost.Close();
                }
            }
            catch (CommunicationException ex)
            {
                Console.WriteLine(ex.Message);
                selfHost.Abort();
                Console.ReadLine();
            }

    2) 用IIS承載,這裡又兩種方式,通過internet的方式 這個可以直接在vs中調試的,選中svc文件點調試會彈出一個wcf的客戶端測試程式,可以直接進行測試,但是這個客戶端不能測試非同步,只能測同步

    這中方式主要是需要配置一個web.config文件,部署的話,直接在IIS添加網站服務程式,把生成的DLL和web.config放在一個目錄下應該跟這個調試是一樣的(這種方式IIS5 6 只支持HTTP)

    還可以通過WAS(進程激活服務,支持的協議比上邊多,這個就沒有深入研究了···)

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

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5.2" />
    <httpRuntime targetFramework="4.5.2"/>
  </system.web>
  <system.serviceModel>
    <services>
      <service name="GettingStartedLib.Calculator" behaviorConfiguration="MyServiceTypeBehaviors" >
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8001/"/>
          </baseAddresses>
        </host>
        <endpoint address="CalculatorService" binding="wsHttpBinding" contract="Calculator">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="MyServiceTypeBehaviors" >
          <!-- 將下列元素添加到服務行為配置中。 -->
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
  <system.webServer>
    <!--<modules runAllManagedModulesForAllRequests="true"/>-->
    <!--
        若要在調試過程中瀏覽 Web 應用程式根目錄,請將下麵的值設置為 True。
        在部署之前將該值設置為 False 可避免泄露 Web 應用程式文件夾信息。
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

  3)通過windows服務程式承載,這個內部起始也是servicehost來實現,只不過是掛在windows服務程式上,需要自己實現一個windows服務,也就是繼承servicebase類,重寫onstart,在onstart中用servicehost載入服務,在stop中停止服務,同時需要配置文件就是程式的配置文件app.config記得生成到目錄下,配置終結點。服務類生成的程式需要安裝,還需要繼承install實現一個安裝類,把生成的服務程式安裝到windows系統服務去,然後就可以在服務中啟動服務,

這個安裝是在管理員許可權下進入對應的.netframework目錄下運行installutil path(程式目錄) 這裡用的是4.5 ,就是v4.0。。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using GettingStartedLib;
using System.ServiceModel.Description;
using System.ServiceModel;
using System.ServiceProcess;
using System.Configuration.Install;
using System.ComponentModel;

namespace WcfConsole
{
    public class serviceCalss : ServiceBase
    {
        public ServiceHost serviceHost = null;
        public serviceCalss()
        {
            ServiceName = "WCFWindowsServiceSample";

        }
        protected override void OnStart(string[] args)
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
            }
            serviceHost = new ServiceHost(typeof(Calculator));

            serviceHost.Open();
        }

        protected override void OnStop()
        {
            if (serviceHost != null)
            {
                serviceHost.Close();
                serviceHost = null;
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            ServiceBase.Run(new serviceCalss());

            //服務的地址
            Uri baseAddress = new Uri("http://localhost:8000/GettingStarted/");
            //承載服務的宿主
            ServiceHost selfHost = new ServiceHost(typeof(Calculator), baseAddress);

            //try
            //{
            //    selfHost.AddServiceEndpoint(typeof(ICalculator), new WSHttpBinding(), "Calculator");
            //    ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
            //    smb.HttpGetEnabled = true;
            //    selfHost.Description.Behaviors.Add(smb);
            //    selfHost.Open();
            //    Console.WriteLine("The service is ready.");
            //    Console.WriteLine("input<exit> to terminate service.");
            //    Console.WriteLine();
            //    while ("exit" == Console.ReadLine())
            //    {
            //        selfHost.Close();
            //    }
            //}
            //catch (CommunicationException ex)
            //{
            //    Console.WriteLine(ex.Message);
            //    selfHost.Abort();
            //    Console.ReadLine();
            //}
        }
    }

    [RunInstaller(true)]
    public class ProjectInstaller : Installer
    {
        private ServiceProcessInstaller process;
        private ServiceInstaller service;

        public ProjectInstaller()
        {
            process = new ServiceProcessInstaller();
            process.Account = ServiceAccount.LocalSystem;
            service = new ServiceInstaller();
            service.ServiceName = "WCFWindowsServiceSample";
            Installers.Add(process);
            Installers.Add(service);
        }
    }
}

對應的配置文件

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
    </startup>
  <system.serviceModel>
    <services>
      <!-- This section is optional with the new configuration model
           introduced in .NET Framework 4. -->
      <service name="GettingStartedLib.Calculator"
               behaviorConfiguration="CalculatorServiceBehavior">
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8000/"/>
          </baseAddresses>
        </host>
        <endpoint address=""
                  binding="wsHttpBinding"
                  contract="Calculator" />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="False"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

4 服務端承載好了,就可以用客戶端調用服務了,又兩種方式

  客戶端直接引用已經運行的服務,vs會自動生成一個對應的client類,裡邊又設置好的服務路徑和介面之類的,也可以自己指定路徑,只用他的函數,記得close

           // CalculatorClient client = new CalculatorClient();
            var client = myChannelFactory.CreateChannel();


            double value1 = 100.00D;
            double value2 = 15.99D;
            double result = client.Add(value1, value2);
            Console.WriteLine("Add({0},{1}) = {2}", value1, value2, result);

  也可以用ChannelFactory<TChannel>類來構造一個client,這種模式是引用服務的契約介面,

     var myBinding = new WSHttpBinding();
            EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/GettingStarted/");
            //EndpointAddress myEndpoint = new EndpointAddress("http://localhost:8000/"); 
            ChannelFactory<ICalculator> myChannelFactory = new ChannelFactory<ICalculator>(myBinding, myEndpoint);

  這裡邊都可以用配置文件來設置終結點,也就是綁定類型和地址,配置方式與服務端類似

5,6就是配置和調用,這裡就不說了

這裡只是簡單的wcf實例,

實際還有內容沒有涉及:

1 不同的綁定類型,怎麼選擇,網上有個圖是判斷什麼情況選擇對應的綁定類型,其實就是選擇協議

2 加密,因為之間的程式用的是basichttpbingding就是就是基本的http綁定,客戶端沒用引用服務端,服務端以web服務的形式公開服務,客戶端直接以http請求的形式來與服務端通信,這樣客戶端cs和bs可以公用一個服務端,但是沒有加密,傳輸的內容是完全公開的··講道理web服務這玩意本來就是發過去給人看的·公開應該也沒啥好像····,面試的時候問到這個問題直接懵逼了···這裡暫時沒寫 ··這玩意好像挺麻煩的···

3 這裡在4.5的環境下編寫的,服務公開以後會自動生成對應的非同步執行方法,與之前的方式不同,之前是老式的beginxxx的非同步方式,返回一個Iasyncresult的結果,這裡是4.5的async/await的形式來執行非同步操作

4 wcf服務是可以相容asp.net ,也可以返回json格式的對象··這個可以通過設置方法的操作特性可以設置

5 wcf服務支持雙工,這個就很流弊了,不過講道理tcp這種本身就支持雙工,沒具體研究

6 在雙工模式下支持回調,這個意思好像是客戶端請求完成再出發一個回調服務麽··· 沒研究···

。。。。。。

 


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • centos7下安裝rabbitmq 折騰了三天最後做了以下總結 先查看一電腦名 :示例 查看一下hosts配置文件:如果如下結果,就要修改下 修改hosts: 如下 安裝相關文件:為了不出錯,要裝 EPEL源,順手安裝一下 redis ...
  • 美國國家安全局(NSA)旗下的“方程式黑客組織”(shadow brokers)使用的部分網路武器被公開,其中包括可以遠程攻破全球約70%Windows機器的漏洞利用工具。 其中,有十款工具最容易影響Windows個人用戶,包括永恆之藍、永恆王者、永恆浪漫、永恆協作、翡翠纖維、古怪地鼠、愛斯基摩捲、 ...
  • 本文為命令ssh的man文檔翻譯,翻譯了90%的內容,剩餘是一些沒必要翻譯的東西,請見諒。 如此文有所疑惑,希望我的另一篇文章能解惑:http://www.cnblogs.com/f-ck-need-u/p/7129122.html SSH(1) BSD General Commands Manua ...
  • 超線程和多線程的區別? 在Linux系統中,如何詳細瞭解CPU的信息呢? 當然是通過cat /proc/cpuinfo來檢查了,但是比如幾個物理CPU/幾核/幾線程,這些問題怎麼確定呢? 經過查看,我的開發機器是1個物理CPU,4核8線程,Intel(R) Core(TM) i7 CPU 860 @ ...
  • 巡檢發現一臺Linux伺服器上的作業沒有如期發送郵件,登錄伺服器檢查後發現作業並沒有執行,於是檢查一下crontab的設置。結果發現如下錯誤: [root@mylnx2 ~]# crontab -l Authentication token is no longer valid; new one r ...
  • 網盤視頻:裡面包含了centos,ubuntu,Solaris 三種目前比較主流的操作系統的安裝,以及他們的開發環境的安裝 https://pan.baidu.com/disk/home#list/vmode=list&path=%2FC%2B%2B%2F%E7%AC%AC%E4%B8%80%E9% ...
  • Spring Batch是一個輕量級的,完全面向Spring的批處理框架,可以應用於企業級大量的數據處理系統。Spring Batch以POJO和大家熟知的Spring框架為基礎,使開發者更容易的訪問和利用企業級服務。Spring Batch可以提供大量的,可重覆的數據處理功能,包括日誌記錄/跟蹤, ...
  • 一:共用賬號檢查 二:來賓賬戶檢查 三:口令複雜度策略 四:口令最長生存期策略 五:遠程關機授權 六:系統關閉授權 七:文件許可權指派 八:匿名許可權限制 八:登陸日誌檢查 九:系統日誌完備性檢查 十:日誌大小設置 十一:遠程登錄超時配置 十二:預設共用檢查 十三:共用許可權檢查 十四:防範病毒管理 十五 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...