WCF简单例子(仿照)

1.建一个wcf服务应用程序:

 

2.定义一个提供wcf服务的接口和数据契约:

namespace WcfService1
{
    // 服务合同 即提供服务的接口或类 
    [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        void AddTicket(uint count);    // 加票

        [OperationContract]
        bool BuyTickets(uint Num);       // 买票

        [OperationContract]
        uint GetRemainingNum();          // 查询余票
    }

    //数据契约 
    [DataContract]
    public class Ticket 
    {
        bool boolCount = true; // 判断还有余票
        uint many = 10;       // 还有多少车票

        public Ticket(uint many)
        {
            this.many = many;
        }

        [DataMember]
        public bool BoolCount
        {
            get { return many > 0; }
        }

        [DataMember]
        public uint Many
        {
            get { return many; }
            set { many = value; }
        }
    }
}

3.实现服务接口:

namespace WcfService1
{
    public class Service1 : IService1
    {
        static Ticket ticket = new Ticket(50); // 保证整个服务生命周期的使用同一车票
        /// <summary>
        /// 追加车票
        /// </summary>
        /// <param name="count"></param>
        /// <returns></returns>
        public void AddTicket(uint count)
        {
            ticket.Many += count;
        }

        /// <summary>
        /// 买票
        /// </summary>
        /// <param name="Num"></param>
        /// <returns></returns>
        public bool BuyTickets(uint Num)
        {
            if (ticket.Many < Num)
            {
                return false;
            }
            else
            {
ticket.Many -= Num;
return true; } } /// <summary> /// 查询余票 /// </summary> /// <returns></returns> public uint GetRemainingNum() { return ticket.Many; } } }

4.对于服务器的web.config的配置暂时不是很熟悉。待分析。

5.添加宿主程序:

新建一个winform解决方案,并把wcf的dll导入引用中,追加开启服务,停止服务按钮。

导入引用:System.ServiceModel。

public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        // 服务主机对象
        ServiceHost host = null;

        private void button1_Click(object sender, EventArgs e)
        {
            // 命名空间+类名
            host = new ServiceHost(typeof(WcfService1.Service1));
            host.Open();
            this.label1.Text = "服务已启动";
        }

        private void button2_Click(object sender, EventArgs e)
        {
            if (host.State != CommunicationState.Closed)
            {
                host.Close();
            }
            this.label1.Text = "服务已停止";
        }
    }

这里的疑问是:为什么每次开启服务都要new对象。

这里要注意的是:new ServiceHost(typeof(WcfService1.Service1))是命名空间+类名,不是命名空间+接口。

6.配置宿主程序的配置文件:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.serviceModel>
    <services>
      <!--添加服务,服务名称必须是wcf的命名空间和类名-->
      <service name="WcfService1.Service1" behaviorConfiguration="CalculatorServiceBehavior">
        <!--name 必须与代码中的host实例初始化的服务一样 
behaviorConfiguration 行为配置 -->
        <host>
          <baseAddresses>
            <!--添加调用服务地址-->
            <add baseAddress="net.tcp://localhost:8133/WCFTcpService"/>
            <add baseAddress="http://localhost:8155/WCFTcpService"/>
          </baseAddresses>

        </host>
        <!--添加契约接口 A:address;B:binding="netTcpBinding" netTcpBinding为通过tcp调用;C:contract="WcfService1.IService1"-->
        <endpoint address="netTcpBinding" binding="netTcpBinding" bindingConfiguration="netTcpBinding" contract="WcfService1.IService1"></endpoint>
      </service>

    </services>

    <!--配置终结点的绑定-->
    <bindings>
      <basicHttpBinding>
        <binding name="basicHttpBinding" closeTimeout="01:01:00" receiveTimeout="01:10:00"
                 sendTimeout="01:01:00" maxReceivedMessageSize="150000002" />
      </basicHttpBinding>
      <wsHttpBinding>
        <binding name="wsHttpBinding" closeTimeout="01:01:00" receiveTimeout="01:10:00" sendTimeout="01:01:00" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" >
          <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
          <security mode="None" />
        </binding>
      </wsHttpBinding>
      <netTcpBinding>
        <binding name="netTcpBinding" closeTimeout="01:01:00" receiveTimeout="01:10:00" sendTimeout="01:01:00"
                 maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" portSharingEnabled="true" listenBacklog="2147483647"
                 maxConnections="2147483647" maxBufferSize="2147483647">
          <readerQuotas maxStringContentLength="2147483647" maxDepth="2147483647" maxBytesPerRead="2147483647"
                        maxNameTableCharCount="2147483647" maxArrayLength="2147483647"/>
          <security mode="None" />
        </binding>
      </netTcpBinding>
    </bindings>
    
    <!--CalculatorServiceBehavior就是终结点行为的名称-->
    <behaviors>
      <serviceBehaviors>
        <behavior name="CalculatorServiceBehavior">
          <serviceMetadata httpGetEnabled="true"/>
          <serviceDebug includeExceptionDetailInFaults="false"/>

        </behavior>

      </serviceBehaviors>

    </behaviors>
  </system.serviceModel>
</configuration>

configuration下的system.serviceModel就是wcf的配置,services就是配置主服务,而services下的behaviorConfiguration的配置就是behaviors节点,这个节点下的httpGetEnabled表示使用Http,service表示前台接受异常。

service的name必须是wcf的名称空间+类名,host下的baseAddresses配置的是地址,现在这里有tcp协议和http协议。

最主要的是:endpoint终结点的配置,这里有三个属性分别是ABC,A代表地址address,这里用的是Tcp协议的地址,B代表binding,这个配置比较精细,在binding节点下,涉及到很多问题,C代表契约接口contract,内容是命名空间+接口名称。

7.开启服务:

按理来说我使用的是TCP协议,不知道为什么开启服务之后连接的是Http协议的地址

http://localhost:8155/WCFTcpService

个人猜想,

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

  <appSettings>
    <add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.5" />
    <httpRuntime targetFramework="4.5"/>
  </system.web>
  <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <!-- 为避免泄漏元数据信息,请在部署前将以下值设置为 false -->
          <serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
          <!-- 要接收故障异常详细信息以进行调试,请将以下值设置为 true。在部署前设置为 false 以避免泄漏异常信息 -->
          <serviceDebug includeExceptionDetailInFaults="false"/>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <protocolMapping>
        <add binding="basicHttpsBinding" scheme="https" />
    </protocolMapping>    
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
  </system.serviceModel>
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <!--
        若要在调试过程中浏览 Web 应用程序根目录,请将下面的值设置为 True。
        在部署之前将该值设置为 False 可避免泄露 Web 应用程序文件夹信息。
      -->
    <directoryBrowse enabled="true"/>
  </system.webServer>

</configuration>

wcf配置的

<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>的原因。待以后在修正。

8.调用服务:

新建winform,含有加票,买票,查票的按钮。

添加服务引用

这里的命名空间SeriveReference1将在接下来使用。

    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }
        string msg = "当前车票为{0}张。";
        ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
        private void Form1_Load(object sender, EventArgs e)
        {
            this.label2.Text = string.Empty;
        }

        private void button1_Click(object sender, EventArgs e)
        {
            client.AddTicket(5);
            this.label2.Text = string.Format(msg, client.GetRemainingNum());
        }

        private void button2_Click(object sender, EventArgs e)
        {
            client.BuyTickets(1);
            this.label2.Text = string.Format(msg, client.GetRemainingNum());
        }

        private void button3_Click(object sender, EventArgs e)
        {
            this.label2.Text = string.Format(msg, client.GetRemainingNum());
        }
    }

接下来是效果图:

 

posted @ 2015-04-17 15:00  江境纣州  阅读(93)  评论(0编辑  收藏  举报