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,整个过程就这样结束了。

  • 相关阅读:
    UVA
    UVA
    模板——扩展欧几里得算法(求ax+by=gcd的解)
    UVA
    模板——2.2 素数筛选和合数分解
    模板——素数筛选
    Educational Codeforces Round 46 (Rated for Div. 2)
    Educational Codeforces Round 46 (Rated for Div. 2) E. We Need More Bosses
    Educational Codeforces Round 46 (Rated for Div. 2) D. Yet Another Problem On a Subsequence
    Educational Codeforces Round 46 (Rated for Div. 2) C. Covered Points Count
  • 原文地址:https://www.cnblogs.com/mingmingruyuedlut/p/3760722.html
Copyright © 2011-2022 走看看