WCF服務使用(IIS+Http)和(Winform宿主+Tcp)兩種方式進行發佈

一、寫在前面
剛接觸WCF不久,有不少地方知其然不知其因此然。當我在【建立服務->發佈服務->使用服務】這一過程出現過許多問題。如客戶端找不到服務引用;客戶端只在本機環境中才能訪問服務,移植到其餘機器上就不能訪問服務(權限問題)等問題。因此寫下這篇文章把我使用http和tcp這兩方式部署服務所出現的問題以及解決方案記錄下來,方便本身下次查看,也能夠看成初學WCF的一個入門小示例吧。
 
二、創建一個WCF服務
首先要編寫一個WCF服務,我在這裏提供一個經過名字查詢年齡的服務,代碼以下:
服務契約:
    [ServiceContract]
    public interface IPeopleInfo
    {
        [OperationContract]
        int GetAge(string name);
    }

 數據契約:瀏覽器

    [DataContract]
    public class People
    {
        public string Name;
        public int Age;
    }

服務實現:服務器

    public class PeopleInfo : IPeopleInfo
    {

        public int GetAge(string name)
        {
            List<People> peopleList = DataFactory.GetPeopleList();
            return peopleList.Find(t =>t.Name==name).Age ;
        }
    }

 輔助類:tcp

    public class DataFactory
    { 
        public static List<People> GetPeopleList()
        {
            List<People> peopleList = new List<People>();
            peopleList.AddRange(new People[] { 
                new People{Name="tjm",Age=18},
                new People{Name="lw",Age=20},
                new People{Name="tj",Age=22},
            });
            return peopleList;
        }
    }

 

二、發佈(部署)服務
在這裏使用兩種方式發佈服務。一:利用iis做爲宿主,使用http通訊協議發佈服務;二:利用Winform程序做爲宿主,使用tcp通訊協議發佈服務。
 
2.一、iis做爲宿主,使用http通訊協議發佈服務
把1中已經編寫好的服務,能夠像部署一個WebService或者是Asp.Net網站同樣部署到局域網上去。這裏的發佈服務的步驟就省略了。發佈成功以後在瀏覽器中進行訪問時出現以下的錯誤:
WCF部署IIS出現「因爲擴展配置問題而沒法提供您請求的頁面。若是該頁面是腳本,請添加處理程序。若是應下載文件,請添加 MIME 映射」的解決辦法
網上有找了不少資料,大部分的解決方案都是說,系統沒有默認iis註冊WCF服務的svc文件的MIME映射,因而我爲iis註冊WCF服務的映射,方法以下:

管理員身份運行C:\Windows\Microsoft.NET\Framework\v3.0\Windows Communication Foundation\ServiceModelReg.exe -i工具

可是註冊完以後,在瀏覽器中瀏覽該網站仍是出現錯誤,錯誤以下:
HTTP 錯誤 404.3 - Not Found,
因而在網上又找到解決方案以下:
使用管理員註冊:C:\Windows\system32>"C:\Windows\Microsoft.NET\Framework\v4.0.30319\ServiceModelReg.exe" -r
註冊完以後直接在控制檯中出現以下錯誤,

Microsoft(R) WCF/WF 註冊工具版本 4.5.0.0學習

版權全部(C) Microsoft Corporation。保留全部權利。網站

用於管理一臺計算機上 WCF 和 WF 組件的安裝和卸載的管理實用工具。this

[錯誤]此 Windows 版本不支持此工具。管理員應改成使用「打開或關閉 Windows 功能」對話框或 dism 命令行工具來安裝/卸載 Windows Communication Foundation 功能。spa

根據錯誤的提示,去控制面板->程序->啓用或關閉Windows功能,以下圖

 

 把我畫紅線的框內的複選框所有勾選,點擊肯定,而後再在iis中再進行瀏覽就可以找到發佈後的WCF服務了,緣由應該是我沒有安裝WCF服務的組件而致使的吧。在瀏覽器中瀏覽服務以下。命令行

若是上述的方法,尚未在iis中成功發佈服務,能夠嘗試。
在window功能中卸載iis和WCF服務,而後再從新安裝配置。
到此,使用iis中利用http協議發WCF服務已經成功了。
 
2.2 利用Winform程序做爲宿主,使用tcp通訊協議發佈服務

首先創建一個Winform項目,界面以下。設計

在這裏使用兩種方式來宿主WCF服務,第一用代碼的方式,第二使用配置文件的方式。
注意:在部署以前須要把第一步中編寫服務的dll引用進來。
1)使用代碼部署WCF服務
代碼以下:
        ServiceHost host;
        private void btnStart_Click(object sender, EventArgs e)
        {
            //使用代碼綁定
            Uri tcpa = new Uri("net.tcp://172.21.212.54:8090/peopleinfo");
            host = new ServiceHost(typeof(FirstWCFService.PeopleInfo), tcpa);
            ServiceMetadataBehavior mBehave = new ServiceMetadataBehavior();
            NetTcpBinding tcpb = new NetTcpBinding();
            host.Description.Behaviors.Add(mBehave);
            host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
            host.AddServiceEndpoint(typeof(FirstWCFService.IPeopleInfo), tcpb, tcpa);

            host.Open();
this.btnStart.Enabled = false;
            this.label1.Text = "Service Running";
}
private void btnStop_Click(object sender, EventArgs e) { if (host != null) { host.Close(); this.label1.Text = "Service Closed"; this.btnStart.Enabled = true; } }

2)使用配置文件

其實使用配置文件和使用代碼理論是差很少的,能夠根據代碼編寫配置文件,上面的代碼分析可知道,服務宿主對象host添加了一個ServiceMetadataBehavior 對象和兩個Endpoint,所以App.config配置文件中的內容以下。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="FirstWCFService.PeopleInfo">
        <!--客戶端用來解釋服務,這個端點若是缺乏服務會發布失敗-->
        <endpoint contract="IMetadataExchange"
           binding="mexTcpBinding" address ="net.tcp://172.21.212.54:8090/peoleinfo/mex"></endpoint>
        <!--提供服務的端點-->
        <endpoint address="net.tcp://172.21.212.54:8090/peoleinfo" binding="netTcpBinding"
            contract="FirstWCFService.IPeopleInfo">

        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

 雖然是用來配置文件,可是開啓服務的代碼仍是須要寫的。代碼以下。

        ServiceHost host;
        private void btnStart_Click(object sender, EventArgs e)
        {
            host = new ServiceHost(typeof(FirstWCFService.PeopleInfo));
            host.Open();
            this.btnStart.Enabled = false;
            this.label1.Text = "Service Running";
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            if (host != null)
            {
                host.Close();
                this.label1.Text = "Service Closed";
                this.btnStart.Enabled = true;
            }
        }

 運行程序,點擊Start按鈕,到此使用Winform做爲宿主來發布WCF服務已經成功了。

 
三、編寫客戶端調用服務。
客戶端使用Winform程序,界面設計以下:
 
而後分別添加使用http和tcp方式發佈的wcf服務。
1)引用iis+http協議發佈的服務
2)引用Winform宿主+tcp協議發佈的服務
服務添加完成以後,在項目中會自動生成一個應用程序的配置文件,裏面記錄了調用WCF服務的信息。配置文件內容以下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IPeopleInfo" />
            </basicHttpBinding>
            <netTcpBinding>
                <binding name="NetTcpBinding_IPeopleInfo">
                </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="http://172.21.212.54/PeopleInfo.svc" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IPeopleInfo" contract="HttpService.IPeopleInfo"
                name="BasicHttpBinding_IPeopleInfo" />
            <endpoint address="net.tcp://172.21.212.54:8090/peoleinfo" binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_IPeopleInfo" contract="TcpService.IPeopleInfo"
                name="NetTcpBinding_IPeopleInfo" />
        </client>
    </system.serviceModel>
</configuration>

 調用服務操做的代碼很是簡單,就相似於操做本地的類同樣,代碼以下: 

        private void bntGet_Click(object sender, EventArgs e)
        {
            string name = this.txtName.Text;
            int age;
            if (rdbHttp.Checked)
            {
                HttpService.PeopleInfoClient httpClient = new HttpService.PeopleInfoClient();
                age = httpClient.GetAge(name);
            }
            else
            {
                TcpService.PeopleInfoClient tcpClient = new TcpService.PeopleInfoClient();
                age = tcpClient.GetAge(name);
            }
            this.txtAge.Text = age.ToString();
        }

 到此,wcf的客戶端編寫完成,結果以下。

 
注意:把wcf的客戶端部署到其餘機器上去運行,選擇http進行調用沒有問題,而選擇tcp調用服務的時候會出現以下錯誤:

System.ServiceModel.Security.SecurityNegotiationException: 服務器已拒絕客戶端憑據。 --->

System.Security.Authentication.InvalidCredentialException: 服務器已拒絕客戶端憑據。 ---> 

System.ComponentModel.Win32Exception: 登陸沒有成功
其中http方式是由iis進行託管的,裏面權限已是配置好的,容許匿名用戶進行訪問,所以在遠程訪問時不會出現問題的。而tcp方式是由咱們本身編寫winform程序管理的,當客戶端在本機時候,是由於它自己就具備window的用戶訪問的權限,所以能夠訪問,當部署到其餘其餘機器上去的時候,已經不具有本機的這種環境,因此當咱們使用winform做爲宿主的時候,要在配置文件中設置權限模式,在這裏使用無需客戶端驗證的方式。在Winform宿主項目的配置文件添加以下內容,紅色加粗標示爲新增的。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <service name="FirstWCFService.PeopleInfo">
        <!--客戶端用來解釋服務,這個端點若是缺乏服務會發布失敗-->
        <endpoint contract="IMetadataExchange"
           binding="mexTcpBinding" address ="net.tcp://172.21.212.54:8090/peoleinfo/mex"></endpoint>
        <!--提供服務的端點-->
        <endpoint address="net.tcp://172.21.212.54:8090/peoleinfo" binding="netTcpBinding"
            contract="FirstWCFService.IPeopleInfo" bindingConfiguration="NoSecurity">
        </endpoint>
      </service>
    </services>
    <bindings> <netTcpBinding> <binding name="NoSecurity"> <security mode="None"/> </binding> </netTcpBinding> </bindings>     <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
</configuration>

 設置完成以後,從新開啓服務。而後在客戶端刪除winform宿主發佈的服務,而且再從新添加,以便在配置文件中從新生成訪問tcp方式的服務端點的配置。更新後的配置文件以下,紅色加粗部分爲更新的。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
                <binding name="BasicHttpBinding_IPeopleInfo" />
            </basicHttpBinding>
            <netTcpBinding>
                <binding name="NetTcpBinding_IPeopleInfo">
                    <security mode="None" />                 </binding>
            </netTcpBinding>
        </bindings>
        <client>
            <endpoint address="http://172.21.212.54/PeopleInfo.svc" binding="basicHttpBinding"
                bindingConfiguration="BasicHttpBinding_IPeopleInfo" contract="HttpService.IPeopleInfo"
                name="BasicHttpBinding_IPeopleInfo" />
            <endpoint address="net.tcp://172.21.212.54:8090/peoleinfo" binding="netTcpBinding"
                bindingConfiguration="NetTcpBinding_IPeopleInfo" contract="TcpService.IPeopleInfo"
                name="NetTcpBinding_IPeopleInfo" />
        </client>
    </system.serviceModel>
</configuration>

 

四、結論
雖然WCF服務的兩種部署方式已經成功了,可是其中有許多的原理還不是太明白,畢竟接觸WCF還不久。但願後面繼續深刻的學習,達到知其然而且知其因此然境界。
相關文章
相關標籤/搜索