zoukankan      html  css  js  c++  java
  • 用C#基于WCF创建TCP的Service供Client端调用

    本文将详细讲解用C#基于WCF创建TCP的Service供Client端调用的详细过程

    1):首先创建一个Windows Service的工程

    2):生成的代码工程结构如下所示

    3):我们将Service1改名为MainService

    4): 添加一个Interface来定义Service的契约

    4.1):截图如下所示

    4.2):IOrderService.cs的代码如下所示

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.ServiceModel;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EricSunService
    {
        [ServiceContract]
        interface IOrderService
        {
            [OperationContract]
            [FaultContract(typeof(ServiceFault))]
            AccountLoginResponse AccountLogin(AccountLoginRequest request);
    
            [OperationContract]
            [FaultContract(typeof(ServiceFault))]
            AccountTopUpResponse AccountTopUp(AccountTopUpRequest request);
        }
    
        [DataContract]
        public class ServiceFault
        {
            [DataMember]
            public string CorrelationId { get; set; }
            [DataMember]
            public string Message { get; set; }
            [DataMember]
            public string Address { get; set; }
        }
    }
    View Code

    5):然后添加其他的类实现对应的Service,并且实现对Service的Host

    5.1):最终的代码工程截图如下所示(这里的EricSunData工程是用于数据类型的定义,为了更好的逻辑结构分层,这里我们主要以AccountLogin.cs中所实现的OrderService进行讲解)

    5.2):AccountLogin.cs的代码如下所示(实现IOrderService中的部分接口)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.Serialization;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EricSunService
    {
        public partial class OrderService : IOrderService
        {
            public AccountLoginResponse AccountLogin(AccountLoginRequest request)
            { 
                // do some logic with account info
                AccountLoginResponse loginResponse = new AccountLoginResponse() { AccountBalance = 10000000.00, Status = new AccountLoginStatus() };
                return loginResponse;
            }
        }
    
    
        [DataContract]
        public class AccountLoginRequest
        {
            [DataMember]
            public string Name { get; set; }
            [DataMember]
            public string Password { get; set; }
        }
    
        [DataContract]
        public class AccountLoginResponse
        {
            [DataMember]
            public double AccountBalance { get; set; }
            [DataMember]
            public AccountLoginStatus Status { get; set; }
        }
    
        public enum AccountLoginStatus
        {
            NoError = 0,
            InvalidAccountInfo // Invalid Account Info
        }
    }
    View Code

    5.3):MainService的代码如下所示 (进行对Service的Host)

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Diagnostics;
    using System.Linq;
    using System.ServiceModel;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EricSunService
    {
        public partial class MainService : ServiceBase
        {
            private ServiceHost _orderService;
    
            public MainService()
            {
                InitializeComponent();
            }
    
            protected override void OnStart(string[] args)
            {
                _orderService = new ServiceHost(typeof(OrderService));
                _orderService.Open();
            }
    
            protected override void OnStop()
            {
                _orderService.Close();
            }
        }
    }
    View Code

    5.4):Program.cs的代码如下所示 (.exe运行时主入口)

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using System.ServiceProcess;
    using System.Text;
    using System.Threading.Tasks;
    
    namespace EricSunService
    {
        static class Program
        {
            /// <summary>
            /// The main entry point for the application.
            /// </summary>
            static void Main()
            {
    #if DEBUG
                ServiceHost host = new ServiceHost(typeof(OrderService));
                host.Open();
                System.Threading.Thread.Sleep(System.Threading.Timeout.Infinite);
    #else
                ServiceBase[] ServicesToRun;
                ServicesToRun = new ServiceBase[] 
                { 
                    new MainService() 
                };
                ServiceBase.Run(ServicesToRun);
    #endif
            }
        }
    }
    View Code

    6):运行Service时的可能错误以及App.config的配置

    6.1):当我们build真个solution之后,到对应的debug目录去运行对应的EricSunService.exe文件时,有可能会出现如下错误,为了解决如下的错误才有了5.4中写法

    6.2):App.config文件的配置信息,是对WCF框架下暴露Service的endpoint(ABC)的一个详细配置

    <?xml version="1.0" encoding="utf-8" ?>
    <configuration>
      <startup> 
          <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
      </startup>
      
      <system.serviceModel>
        <behaviors>
          <serviceBehaviors>
            <behavior name="OrderServiceBehavior">
              <serviceMetadata httpGetEnabled="false" />
              <serviceDebug />
            </behavior>
          </serviceBehaviors>
        </behaviors>
        <services>
          <service behaviorConfiguration="OrderServiceBehavior" name="EricSunService.OrderService">
            <host>
              <baseAddresses>
                <add baseAddress="net.tcp://localhost:3434/" />
              </baseAddresses>
            </host>
            <endpoint address="" binding="netTcpBinding" bindingConfiguration="NetTcpBindingConfig" contract="EricSunService.IOrderService"/>
            <endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange" />
          </service>
        </services>
        <bindings>
          <netTcpBinding>
            <binding name="NetTcpBindingConfig">
              <security mode="None" />
            </binding>
          </netTcpBinding>
        </bindings>
      </system.serviceModel>
    
    </configuration>
    View Code

    7):创建一个Asp.Net MVC 的工程作为Client端去调用所提供的Service,之后是添加对OrderService的引用,如下图所示

    8):在EricSunService.exe运行起来的状态下,去update此OrderServiceReference,如下图所示

    9):点击Show All Files之后会看到如下详细的工程文件信息

    10):同时我们发现了如下图的错误信息

    11):为了解决这个错误信息,请按下图的步骤进行操作

    11.1):鼠标右键点击OrderServiceReference后选择Config Service Reference

    11.2):取消对Reuse types in referenced assemblies的勾选

    11.3):点击上图中的OK按钮之后,生成了Service所对应Data的详细信息,如下图所示

    11.4):最终的工程结构如下图所示

    12):Service的引用添加完毕之后,就可以对Service进行调用了,我们这里选择的是ChannelFactory的方式,详细代码如下所示

    12.1):OrderServiceClientFactory.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using System.Web;
    using EricSunWeb.OrderServiceReference;
    
    namespace EricSunWeb.Business
    {
        public static class OrderServiceClientFactory
        {
            private static readonly object CRITICAL_SECTION = new object();
            private static ChannelFactory<IOrderServiceChannel> s_ChannelFactory = null;
    
            public static IOrderServiceChannel CreateClient()
            {
                if (s_ChannelFactory == null || s_ChannelFactory.State == CommunicationState.Faulted)
                {
                    lock (CRITICAL_SECTION)
                    {
                        if (s_ChannelFactory == null)
                        {
                            s_ChannelFactory = new ChannelFactory<IOrderServiceChannel>("NetTcpBinding_IOrderService");
                        }
                        else if (s_ChannelFactory.State == CommunicationState.Faulted)
                        {
                            s_ChannelFactory.Abort();
                            s_ChannelFactory = new ChannelFactory<IOrderServiceChannel>("NetTcpBinding_IOrderService");
                        }
                    }
                }
    
                return s_ChannelFactory.CreateChannel();
            }
        }
    }
    View Code

    12.2):OrderManager.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using EricSunWeb.OrderServiceReference;
    
    namespace EricSunWeb.Business
    {
        public class OrderManager
        {
            public void AccountLogin(string name, string password)
            {
                var request = new AccountLoginRequest
                {
                    Name = name,
                    Password = password
                };
    
                AccountLoginResponse response = null;
                var client = OrderServiceClientFactory.CreateClient();
                response = client.AccountLogin(request);
    
                if (response.Status == AccountLoginStatus.NoError)
                {
    
                }
                else
                { 
                    
                }
            }
        }
    }
    View Code

    12.3):OrderController.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using EricSunWeb.Business;
    using EricSunWeb.OrderServiceReference;
    
    namespace EricSunWeb.Controllers
    {
        public class OrderController : Controller
        {
            //
            // GET: /Order/
    
            public ActionResult Index()
            {
                new OrderManager().AccountLogin("EricSun", "password");
                return View();
            }
    
        }
    }
    View Code

    OK,整个过程就这样结束了。

  • 相关阅读:
    秦曾昌人工智能课程---6、Decision Tree Learning
    秦曾昌人工智能课程---5、KNN和朴素贝叶斯
    秦曾昌人工智能课程---4、梯度下降算法
    我和最小二乘法的二三事
    英语影视台词---The Professor
    秦曾昌人工智能课程---3、机器学习中的哲学
    python从入门到大神---1、初始化实例、类属性、方法
    秒懂神经网络---震惊!!!神经网络原来可以这么简单!
    秦曾昌人工智能课程---2、机器学习中的数学基础2
    linuxc_螺纹锁紧pthread_mutex_t
  • 原文地址:https://www.cnblogs.com/mingmingruyuedlut/p/3760722.html
Copyright © 2011-2022 走看看