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调用服务的时候会出现如下错误:

服务器已拒绝客户端凭据

其中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还不久。希望后面继续深入的学习,达到知其然并且知其所以然境界。

时间: 2025-01-07 12:51:20

WCF服务使用(IIS+Http)和(Winform宿主+Tcp)两种方式进行发布的相关文章

WCF 一步一步 发布 WCF服务 到 IIS (图)

WCF 一步一步 发布 WCF服务 到 IIS (图) 使用VS自带的WCFSVCHost(WCF服务主机)发布WCF服务,时刻开发人员测试使用. 下面我们来看一下如何在IIS中部发布一个WCF服务. 环境是VS 2008 (公司电脑没有安装VS2010)^_^ 我们从头开始,不写代码,完全的配置,会收获不小. 新建一个WCF 服务库 建立一个WCF服务应用程序 结果如下 删除掉WCF程序中不需要的默认文件,如下图   为WcfService1项目添加WcfServiceLibrary1的引用,

不停止MySQL服务增加从库的两种方式

转载自:http://lizhenliang.blog.51cto.com/7876557/1669829 现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. 一般在线增加从库有两种方式,一种是通过mysqldump备份主库,恢复到从库,mysqldump是逻辑备份,数据量大时,备份速度会很慢,锁表的时间也会很长.另一种是通过xtrabackup工具

不停止 MySQL 服务增加从库的两种方式

不停止 MySQL 服务增加从库的两种方式 提交 我的评论 加载中 已评论 不停止 MySQL 服务增加从库的两种方式 2015-07-12 数据库开发 数据库开发 数据库开发 微信号 DBDevs 功能介绍 分享数据库相关技术文章.教程和工具,另外还包括数据库相关的工作.偶尔也谈谈程序员人生 :) (点击上方蓝字,快速关注我们) 作者:李振良 网址:http://lizhenliang.blog.51cto.com/7876557/1669829 现在生产环境MySQL数据库是一主一从,由于业

不停止MySQL服务增加从库的两种方式【转载】

现在生产环境MySQL数据库是一主一从,由于业务量访问不断增大,故再增加一台从库.前提是不能影响线上业务使用,也就是说不能重启MySQL服务,为了避免出现其他情况,选择在网站访问量低峰期时间段操作. 一般在线增加从库有两种方式,一种是通过mysqldump备份主库,恢复到从库,mysqldump是逻辑备份,数据量大时,备份速度会很慢,锁表的时间也会很长.另一种是通过xtrabackup工具备份主库,恢复到从库,xtrabackup是物理备份,备份速度快,不锁表.为什么不锁表?因为自身会监控主库日

XFire构建服务端Service的两种方式

1.原声构建:2.集成spring构建 http://blog.csdn.net/carefree31441/article/details/4000436XFire构建服务端Service的两种方式

springboot 注册服务注册中心(zk)的两种方式

在使用springboot进行开发的过程中,我们经常需要处理这样的场景:在服务启动的时候,需要向服务注册中心(例如zk)注册服务状态,以便当服务状态改变的时候,可以故障摘除和负载均衡. 我遇到过两种注册的途径: 1.在Spring的webapplication启动完成后,直接进行注册: 2.在servlet容器启动完成后,通过listener进行注册. 本文通过一个demo讲述一下这两种注册方式,使用的是传统的向zk注册的方案. 1.Spring webapplication启动完成后注册 先上

springcloud 服务调用的两种方式

spring-cloud调用服务有两种方式,一种是Ribbon+RestTemplate, 另外一种是Feign.Ribbon是一个基于HTTP和TCP客户端的负载均衡器,其实feign也使用了ribbon, 只要使用@FeignClient时,ribbon就会自动使用. 一.Ribbon 1.1新建模块client-apom文件 <?xml version="1.0" encoding="UTF-8"?> <project xmlns="

Mock服务端:客户端Get请求,返回json数据两种方式

Mock服务端:客户端Get请求,返回json数据两种方式:1,直接在response中返回json数据 2,通过json文件返回: 准备工作: wiremock-body-transformer-1.1.6.jar wiremock-standalone-2.14.0.jar 安装java运行环境(jdk等) 一,直接在response中返回: 说明: mappings : 对应请求request位置 __files : 对应响应reponse位置 mappings中增减文件:get.json

WCF服务寄宿IIS与Windows服务

WCF是Windows平台下程序间通讯的应用程序框架.整合和 .net Remoting,WebService,Socket的机制,是用来开发windows平台上分布式开发的最佳选择.wcf程序的运行需要一个宿主ServiceHost,我们可以选用控制台应用程序,也可以选择IIS寄宿,还可以选择windows 服务寄宿.相较与控制台程序,IIS,和Windows服务比较稳定.而且大家不会时不时的去重启下IIS下的网站,或者windows服务. 在IIS下寄宿Wcf 我们新建一个类库项目 在项目下