用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,整個過程就這樣結束了。

 

 

 

 

 


免責聲明!

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



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