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


1、寫在前面
剛接觸WCF不久,有很多地方知其然不知其所以然。當我在【創建服務->發布服務->使用服務】這一過程出現過許多問題。如客戶端找不到服務引用;客戶端只在本機環境中才能訪問服務,移植到其他機器上就不能訪問服務(權限問題)等問題。所以寫下這篇文章把我使用http和tcp這兩方式部署服務所出現的問題以及解決方案記錄下來,方便自己下次查看,也可以當作初學WCF的一個入門小示例吧。
 
2、建立一個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 ;
        }
    }

 輔助類:

    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;
        }
    }

 

2、發布(部署)服務
在這里使用兩種方式發布服務。一:利用iis作為宿主,使用http通信協議發布服務;二:利用Winform程序作為宿主,使用tcp通信協議發布服務。
 
2.1、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 組件的安裝和卸載的管理實用工具。

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

根據錯誤的提示,去控制面板->程序->啟用或關閉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服務已經成功了。

 
3、編寫客戶端調用服務。
客戶端使用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>

 

4、結論
雖然WCF服務的兩種部署方式已經成功了,但是其中有許多的原理還不是太明白,畢竟接觸WCF還不久。希望后面繼續深入的學習,達到知其然並且知其所以然境界。
 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM