C#/.NET 分布式专题(SOA【面向服务】WCF的使用)

WCF相比于webservice特点是:
支持不同的协议:http tcp IPC MSMQ p2p
支持不同的宿主:网站 控制台 winform WindowsService
双工协议(可在接的同时进行发)

下面来说说WebService的使用第一种方法:

一:在asp.net网站的路由中配置如下代码

public class RouteConfig
{
    public static void RegisterRoutes(RouteCollection routes)
    {
        routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
        routes.IgnoreRoute("Remote/{*pathInfo}");//忽略以Remote开头

        routes.MapRoute(
            name: "Default",
            url: "{controller}/{action}/{id}",
            defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
        );
    }
}

二:服务端

// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码、svc 和配置文件中的类名“CustomService”。
// 注意: 为了启动 WCF 测试客户端以测试此服务,请在解决方案资源管理器中选择 CustomService.svc 或 CustomService.svc.cs,然后开始调试。
public class CustomService : ICustomService
{
    public void DoWork()
    {
        Console.WriteLine("1234");
    }

    public int Get()
    {
        return DateTime.Now.Year;
    }

    public int GetNoAttribuet()
    {
        return DateTime.Now.Year;
    }

    public UserInfo GetUser()
    {
        return new UserInfo()
        {
            Id = 123,
            Name = "董小姐",
            Age = 19
        };
    }
}

ICustomService类

// 注意: 使用“重构”菜单上的“重命名”命令,可以同时更改代码和配置文件中的接口名“ICustomService”。
[ServiceContract]
public interface ICustomService
{
	//只有标记OperationContract才能在客户端使用
    [OperationContract]
    void DoWork();


    [OperationContract]
    int Get();

    int GetNoAttribuet();


    [OperationContract]
    UserInfo GetUser();

}

userinfo类

// 实体没有无参数构造  需要添加DataContract
//类上面有DataContractAttribute,那么元素需要[DataMember],否则不可见
[DataContractAttribute]
public class UserInfo
{
    public UserInfo()
    { }

    [DataMember]
    public int Id { get; set; }
    [DataMember]
    public string Name { get; set; }
    public int Age { get; set; }
}

下面来说说WebService的使用第二种方法:

引入命名空间:using System.ServiceModel;

//ServiceHost对象
List<ServiceHost> hosts = new List<ServiceHost>()
{
//MathService和CalculatorService相当于上面的CustomService,
    new ServiceHost(typeof(MathService)),
    new ServiceHost(typeof(CalculatorService))
};
foreach (var host in hosts)
{
    host.Opening += (s, e) => Console.WriteLine($"{host.GetType().Name} 准备打开");
    host.Opened += (s, e) => Console.WriteLine($"{host.GetType().Name} 已经正常打开");
    host.Closing += (s, e) => Console.WriteLine($"{host.GetType().Name} 准备关闭");
    host.Closed += (s, e) => Console.WriteLine($"{host.GetType().Name} 准备关闭");

    host.Open();
}
Console.WriteLine("输入任何字符,就停止");
Console.Read();
foreach (var host in hosts)
{
    host.Close();
}
Console.Read();

配置文件加入下面一段才能使用

<system.serviceModel>
 <behaviors>
   <serviceBehaviors>
     <behavior name="MathServicebehavior">
       <serviceDebug httpHelpPageEnabled="false"/>
       <serviceMetadata httpGetEnabled="false"/>
       <serviceTimeouts transactionTimeout="00:10:00"/>
       <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>
     </behavior>

     <behavior name="CalculatorServicebehavior">
       <serviceDebug httpHelpPageEnabled="false"/>
       <serviceMetadata httpGetEnabled="false"/>
       <serviceTimeouts transactionTimeout="00:10:00"/>
       <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>
     </behavior>
   </serviceBehaviors>
 </behaviors>

 <bindings>
   <netTcpBinding>
     <binding name="tcpbinding">
       <security mode="None">
         <transport clientCredentialType="None" protectionLevel="None"/>
       </security>
     </binding>
   </netTcpBinding>
 </bindings>
 <services>
   <service name="SOA.WCF.Service.CalculatorService" behaviorConfiguration="CalculatorServicebehavior">
     <host>
       <baseAddresses>
         <add baseAddress="net.tcp://localhost:11111/CalculatorService"/>
       </baseAddresses>
     </host>
     <endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpbinding" contract="SOA.WCF.Interface.ICalculatorService"/>
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
   </service>

   <service name="SOA.WCF.Service.MathService" behaviorConfiguration="MathServicebehavior">
     <host>
       <baseAddresses>
         <add baseAddress="net.tcp://localhost:11111/MathService"/>
       </baseAddresses>
     </host>
     <endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpbinding" contract="SOA.WCF.Interface.IMathService"/>
     <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange"/>
   </service>
 </services>

 <behaviors>
   <serviceBehaviors>
     <behavior name="MathServicebehavior">
       <serviceDebug httpHelpPageEnabled="false"/>
       <serviceMetadata httpGetEnabled="false"/>
       <serviceTimeouts transactionTimeout="00:10:00"/>
       <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>
     </behavior>
   </serviceBehaviors>
 </behaviors>
 
 <bindings>
   <basicHttpBinding>
     <binding name="httpbinding"/>
   </basicHttpBinding>
 </bindings>
 
 <services>
   <service name="SOA.WCF.Service.MathService" behaviorConfiguration="MathServicebehavior">
     <host>
       <baseAddresses>
         <add baseAddress="http://localhost:11113/MathService"/>
       </baseAddresses>
     </host>
     <endpoint address="" binding="basicHttpBinding" bindingConfiguration="httpbinding" contract="SOA.WCF.Interface.IMathService"/>
     <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
   </service>
 </services>

</system.serviceModel>

二:客户端
引用服务后如下方式使用

[TestClass]
 public class UnitTestWCF
 {
     [TestMethod]
     public void TestMethod1()
     {
         int i = 3 + 4;

         MyWCFTest.CustomServiceClient client = null;
         try
         {
             client = new MyWCFTest.CustomServiceClient();
             int iResult = client.Get();
             //int iResult2 = client.GetNoAttribuet();
             var user = client.GetUser();
             client.Close();
         }
         catch (Exception ex)
         {
             if (client != null)
                 client.Abort();//是为了应对网络断掉异常
             Console.WriteLine(ex.Message);
         }

         //using (MyWCFTest.CustomServiceClient client = new MyWCFTest.CustomServiceClient())
         //{
         //    client.DoWork();
         //    int iResult = client.Get();
         //    //int iResult2 = client.GetNoAttribuet();
         //    var user = client.GetUser();
         //}
     }
 }

双工版的服务端:

接口

[ServiceContract(CallbackContract = typeof(ICallBack))]
public interface ICalculatorService
{
    [OperationContract(IsOneWay = true)]
    void Plus(int x, int y);


}

回调ICallBack

/// <summary>
/// 不需要协议  是个约束,由客户端实现
/// </summary>
public interface ICallBack
{
    [OperationContract(IsOneWay = true)]
    void Show(int m, int n, int result);
}
public class CalculatorService : ICalculatorService
{
    /// <summary>
    /// 完成计算,然后去回调
    /// </summary>
    /// <param name="x"></param>
    /// <param name="y"></param>
    public void Plus(int x, int y)
    {
        int result = x + y;
        Thread.Sleep(2000);
        ICallBack callBack = OperationContext.Current.GetCallbackChannel<ICallBack>();
        callBack.Show(x, y, result);
    }
}

使用方式和上面介绍的一样

扫描二维码关注公众号,回复: 8537104 查看本文章
//ServiceHost对象
List<ServiceHost> hosts = new List<ServiceHost>()
{
    new ServiceHost(typeof(MathService)),
    new ServiceHost(typeof(CalculatorService))
};
foreach (var host in hosts)
{
    host.Opening += (s, e) => Console.WriteLine($"{host.GetType().Name} 准备打开");
    host.Opened += (s, e) => Console.WriteLine($"{host.GetType().Name} 已经正常打开");
    host.Closing += (s, e) => Console.WriteLine($"{host.GetType().Name} 准备关闭");
    host.Closed += (s, e) => Console.WriteLine($"{host.GetType().Name} 准备关闭");

    host.Open();
}
Console.WriteLine("输入任何字符,就停止");
Console.Read();
foreach (var host in hosts)
{
    host.Close();
}
Console.Read();

双工客户端使用

继承服务端回调函数

public class CustomCallback : MyConsoleWCTTcpDouble.ICalculatorServiceCallback
    {
        public void Show(int m, int n, int result)
        {
            Console.WriteLine($"回调:{m}+{n}={result} ThreadId:{Thread.CurrentThread.ManagedThreadId}");
        }
    }
class Program
{
   static void Main(string[] args)
   {
       MyConsoleWCTTcpDouble.CalculatorServiceClient client = null;
       try
       {
           Console.WriteLine($"双工调用开始 {Thread.CurrentThread.ManagedThreadId}");
           InstanceContext callbackInstance = new InstanceContext(new CustomCallback());
           client = new MyConsoleWCTTcpDouble.CalculatorServiceClient(callbackInstance);
           client.Plus(123, 234);
           client.Close();
           Console.WriteLine($"双工调用结束 {Thread.CurrentThread.ManagedThreadId}");
       }
       catch (Exception ex)
       {
           if (client != null)
               client.Abort();
           Console.WriteLine(ex.Message);
       }
       Console.ReadLine();
   }
}
发布了143 篇原创文章 · 获赞 117 · 访问量 4246

猜你喜欢

转载自blog.csdn.net/weixin_41181778/article/details/103846213