• .Net Remoting的双向通信和Windows Service的宿主服务


         作为微软分布式技术之一的.Net Remoting,从性能、安全等各方面来说都是相对比较稳定的,也是一项比较成熟的分布式技术。

         从学习.Net Remoting至今,仅仅只使用了一次这门技术,是在去年的一个IM产品中。最近公司的产品出现了很多问题,服务器、通信接口、网站都陆续被攻击(DDOS)。这对于做互联网产业的同行来说就清楚这里面的关系,强大的DDOS攻击可以直接让产品无法正常运营甚至停止运营。

         经过一系列的分析,我打算使用.Net Remoting这门技术人为的通过编程开发的方式来解决上述的一些问题。其中.Net Remoting的双向通信机制可以解决产品中的部门业务流程(比如在线充值,充值成功|失败通知客户端),从通信效率上来说也优于WEB应用接口(比如Alipay的支付接口)。基于Windows Service的宿主服务、或通过IIS来宿主Remoting的服务都是比较方便的。不过我放弃了基于IIS部署.Net Remoting,IIS部署的服务始终都无法逃避开DDOS的攻击。 Windows Service相比之下更适合于防止DDOS攻击。

         现在有一个小的功能需求,我们要做一个聊天应用,要求使用.Net Remoting来提供远程接口,当客户端调用.Net Remoting远程接口发送消息到服务器后,服务器对详细进行一系列的处理(如在多人聊天的情况下广播消息,一对一聊天的情况下传递消息到另一客户端,其中还可能包括写数据库等多项操作),这里为了方便演示我就将消息回发给自己。

         好的,了解清楚了需求我们可以定义两个接口,一个应用于发送消息的接口,一个应用于回发消息的接口,从某种角度(如WCF中)也可以叫契约。

     1 namespace ChatRoom.Contract
     2 {
     3     public interface IDuplexChat
     4     {
     5         void SendMessage(string message, IChatCallback callBack);
     6     }
     7 }
     8 namespace ChatRoom.Contract
     9 {
    10     /// <summary>
    11     /// 服务器端回调接口
    12     /// </summary>
    13     public interface IChatCallback
    14     {
    15         /// <summary>
    16         /// 回调方法,显示聊天消息
    17         /// </summary>
    18         /// <param name="message"></param>
    19         void ShowMessage(string message);
    20     }
    21 }

         接口定义好了,现在可以提供Remoting远程服务了,既然是.Net Remoting远程服务,那么就必须继承于MarshalByRefObject,同时我们还实现IDuplexChat接口,如下:

     1 namespace ChatRoom.Remoting
     2 {
     3     public class DuplexChatRemoting : MarshalByRefObject, IDuplexChat
     4     {
     5         public void SendMessage(string message, IChatCallback callBack)
     6         {
     7             Console.WriteLine("Invoke the method SendMessage()");
     8 
     9             //do other
    10             callBack.ShowMessage(message);
    11         }
    12     }
    13 }

         通常开发.Net Remoting程序都会有宿主、服务和客户端三个基本的程序模块。上面已经实现了Remoting服务,接下来就需要将该服务通过一种特定的方式来宿主(控制台程序、IIS或Windows Service)服务,宿主服务也就是将远程服务公布出来,并提供一种远程连接的方式,通常也称其为通道(信道)。鉴于程序的灵活性我们可通过配置文件的方式来配置.Net Remoting,比如我们通过控制台程序来宿主服务,如下配置代码块:

     1 <?xml version="1.0" encoding="utf-8" ?>
     2 <configuration>
     3   <system.runtime.remoting>
     4     <application name="ChatRoom">
     5       <service>
     6         <wellknown mode="SingleCall" type="ChatRoom.Remoting.DuplexChatRemoting,ChatRoom.Remoting" objectUri="ChatRoomURL"></wellknown>
     7       </service>
     8       <channels>
     9         <channel ref="http" port="8080">
    10           <serverProviders>
    11             <provider ref="wsdl"></provider>
    12             <formatter ref="binary" typeFilterLevel="Full"></formatter>
    13           </serverProviders>
    14           <clientProviders>
    15             <formatter ref="binary"></formatter>
    16           </clientProviders>
    17         </channel>
    18       </channels>
    19     </application>
    20   </system.runtime.remoting>
    21 </configuration>
     1 namespace ChatRoom.ConsoleHost
     2 {
     3     class Program
     4     {
     5         static void Main(string[] args)
     6         {
     7             RemotingConfiguration.Configure("ChatRoom.ConsoleHost.exe.config"false);
     8             Console.WriteLine(".Net Remoting 服务已启动");
     9             Console.Read();
    10         }
    11     }
    12 }

          宿主和服务都提供好,现在我们需要一个调用客户端,远程服务已经通过宿主提供好了并定义好了通信信道。那么客户端也得遵守宿主里提供的通信规则,既按照宿主里提供的通信地址和端口进行通信。

    Code

         客户端的调用示例程序代码块:

     1 namespace ChatRoom.Client
     2 {
     3     class Program
     4     {
     5         static IDuplexChat proxy = null;
     6         static string message = string.Empty;
     7 
     8         static void Main(string[] args)
     9         {
    10             RemotingConfiguration.Configure("ChatRoom.Client.exe.config"false);
    11             proxy  = (IDuplexChat)Activator.GetObject(typeof(IDuplexChat), "http://localhost:8080/ChatRoom/ChatRoomURL");
    12 
    13             message = Console.ReadLine();
    14             SendMessage(message);
    15         }
    16 
    17         private static void SendMessage(string message)
    18         {
    19             proxy.SendMessage(message, new ChatRoomCallBackHandler());
    20 
    21             message = Console.ReadLine();
    22             if (message != "exit")
    23             {
    24                 SendMessage(message);
    25             }
    26         }
    27     }
    28 }

         OK,如上便可完成一个双向通信(Client---Server|Server---Client)的简单应用。通过上面使用控制台的方式来宿主.Net Remoting的远程服务,如果不小心关闭了控制台也就管理了远程服务,每次使用远程服务都需要先确保服务已经成功启动,这是非常麻烦的事情。

         我们可以通过Windows服务来避免不小心关闭远程服务的缺点,建立Windows服务项目,直接将上面控制台程序里的配置文件复制到Windows服务项目里,在默认的Server1的代码文件下装载.Net Remoting服务就OK:

    1 protected override void OnStart(string[] args)
    2 {
    3     RemotingConfiguration.Configure("ChatRoom.WinServiceHost.exe.config"false);
    4 }

         光这样是不能完成Windows服务的开安并成功安装,还需要一个安装程序类来对Windows服务进行一些设置。详细请查询Windows服务开发相关的资料。

         

         最后只需要将windows服务安装到计算机上就OK。

         本文示例代码下载:ChatRoom.rar

    版权说明

      本文属原创文章,欢迎转载,其版权归作者和博客园共有。  

      作      者:Beniao

     文章出处:http://beniao.cnblogs.com/  或  http://www.cnblogs.com/

  • 相关阅读:
    acwing 164. 可达性统计(拓扑排序+位运算,bitset使用)
    csp 2020062 稀疏向量(双指针)
    acwing 二分图的最大匹配(匈牙利算法)
    acwing 860. 染色法判定二分图(dfs,bfs)
    acwing 1140. 最短网络(prim)
    acwing 3745. 牛的学术圈 I(构造)
    CF585F Digits of Number Pi
    剩余系建图
    P5445 [APIO2019]路灯
    P8097 [USACO22JAN] Farm Updates G
  • 原文地址:https://www.cnblogs.com/beniao/p/1420711.html
Copyright © 2020-2023  润新知