原文:.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.  1 namespace ChatRoom.Contract
  2.  
  3.  2 {
  4.  
  5.  3     public interface IDuplexChat
  6.  
  7.  4     {
  8.  
  9.  5         void SendMessage(string message, IChatCallback callBack);
  10.  
  11.  6     }
  12.  
  13.  7 }
  14.  
  15.  8 namespace ChatRoom.Contract
  16.  
  17.  9 {
  18.  
  19.      /// <summary>
  20.  
  21.      /// 服务器端回调接口
  22.  
  23.      /// </summary>
  24.  
  25.      public interface IChatCallback
  26.  
  27.      {
  28.  
  29.          /// <summary>
  30.  
  31.          /// 回调方法,显示聊天消息
  32.  
  33.          /// </summary>
  34.  
  35.          /// <param name="message"></param>
  36.  
  37.          void ShowMessage(string message);
  38.  
  39.      }
  40.  
  41.  }

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

  1.  1 namespace ChatRoom.Remoting
  2.  
  3.  2 {
  4.  
  5.  3     public class DuplexChatRemoting : MarshalByRefObject, IDuplexChat
  6.  
  7.  4     {
  8.  
  9.  5         public void SendMessage(string message, IChatCallback callBack)
  10.  
  11.  6         {
  12.  
  13.  7             Console.WriteLine("Invoke the method SendMessage()");
  14.  
  15.  8 
  16.  
  17.  9             //do other
  18.  
  19.              callBack.ShowMessage(message);
  20.  
  21.          }
  22.  
  23.      }
  24.  
  25.  }

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

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

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

  1. Code
  2.  
  3.  1 <?xml version="1.0" encoding="utf-8" ?>
  4.  
  5.  2 <configuration>
  6.  
  7.  3   <system.runtime.remoting>
  8.  
  9.  4     <application>
  10.  
  11.  5       <channels>
  12.  
  13.  6         <channel ref="http" port="">
  14.  
  15.  7           <serverProviders>
  16.  
  17.  8             <provider ref="wsdl"></provider>
  18.  
  19.  9             <formatter ref="binary" typeFilterLevel="Full"></formatter>
  20.  
  21.            </serverProviders>
  22.  
  23.            <clientProviders>
  24.  
  25.              <formatter ref="binary"></formatter>
  26.  
  27.            </clientProviders>
  28.  
  29.          </channel>
  30.  
  31.        </channels>
  32.  
  33.      </application>
  34.  
  35.    </system.runtime.remoting>
  36.  
  37.  </configuration>

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

  1.  1 namespace ChatRoom.Client
  2.  
  3.  2 {
  4.  
  5.  3     class Program
  6.  
  7.  4     {
  8.  
  9.  5         static IDuplexChat proxy = null;
  10.  
  11.  6         static string message = string.Empty;
  12.  
  13.  7 
  14.  
  15.  8         static void Main(string[] args)
  16.  
  17.  9         {
  18.  
  19.              RemotingConfiguration.Configure("ChatRoom.Client.exe.config", false);
  20.  
  21.              proxy  = (IDuplexChat)Activator.GetObject(typeof(IDuplexChat), "http://localhost:8080/ChatRoom/ChatRoomURL");
  22.  
  23.  
  24.  
  25.              message = Console.ReadLine();
  26.  
  27.              SendMessage(message);
  28.  
  29.          }
  30.  
  31.  
  32.  
  33.          private static void SendMessage(string message)
  34.  
  35.          {
  36.  
  37.              proxy.SendMessage(message, new ChatRoomCallBackHandler());
  38.  
  39.  
  40.  
  41.              message = Console.ReadLine();
  42.  
  43.              if (message != "exit")
  44.  
  45.              {
  46.  
  47.                  SendMessage(message);
  48.  
  49.              }
  50.  
  51.          }
  52.  
  53.      }
  54.  
  55.  }

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

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

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

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

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

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

版权说明

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

作      者:Beniao

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

.Net Remoting的双向通信和Windows Service的宿主服务的更多相关文章

  1. windows service自动重启服务

    服务一般都能正常的运行,但有时候也会有一些假死现象,比如公司有一考勤服务就因为依赖于硬件厂家的api, 但厂家api运行一段时间后会默名的假死,引起整个服务假死,因为这一假死现象具有不确定性,所以不太 ...

  2. windows service宿主web api使用"依赖注入"和“控制反转”的技术实践

    前言 自从几年前抛弃wcf,使用web api 来做服务器端开发之后,就不再迷惑了.但是因为本来从事传统行业管理软件开发,一般都以分布式应用开发为主.纯BS还是比较少,于是比较喜欢用windows s ...

  3. 关于Windows Service的一个编写技巧

    写过Windows Service的朋友都知道服务是不可以直接在vs里面启动调试,我们必须修改Program.cs文件来达到我们调试的目的,等服务调试好了以后还要把代码改回来,显非常的不方便,在这里为 ...

  4. 从Web Service和Remoting Service引出WCF服务

    本篇先通过Web Service和Remoting Service创建服务,抛砖引玉,再体验WCF服务.首先一些基本面: 什么是WCF? Windows Communication Foundatio ...

  5. quartz.net结合Topshelf实现windows service服务托管的作业调度框架

    topshelf可以很简单方便的实现windows service服务,详见我的一篇博客的介绍 http://www.cnblogs.com/xiaopotian/articles/5428361.h ...

  6. windows Service 之调试过程(附加到进程里调试,而且启动时间不能超过30秒)

    最近第一次用C#写了一个windows service ,其实实现的内容比较简单.就是启动remoting 连接,但是调试相对初次写windws service 的我来说,比较烦.没有经验,而且没办法 ...

  7. C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程

    前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...

  8. 如何利用mono把.net windows service程序迁移到linux上

    How to migrate a .NET Windows Service application to Linux using mono? 写在最前:之所以用要把windows程序迁移到Linux上 ...

  9. 如何托管ASP.NET Core应用到Windows Service中

    (此文章同时发表在本人微信公众号"dotNET开发经验谈",欢迎右边二维码来关注.) 题记:正在构思一个中间件的设计,考虑是否既可以使用最新的技术,也可以兼顾传统的部署模式.所以有 ...

随机推荐

  1. [Node] Run Local DevDependencies from the Command Line with npx

    In the past, you've needed to either write a package.json script or use the node_modules/.bin direct ...

  2. Java反射学习总结二(用反射调用对象的私有属性和方法)

    大家都知道正常的调用是不可以访问对象的private修饰的属性和方法的,这也是Java的封装性原则. 但是有没有方法可以强制去访问对象的private修饰的属性和方法呢?那就是用反射!(这个可能在面试 ...

  3. bootstrap课程2 bootstrap的栅格系统的主要作用是什么

    bootstrap课程2  bootstrap的栅格系统的主要作用是什么 一.总结 一句话总结:响应式布局(就是适应不同的屏幕,手机,平板,电脑) 1.bootstrap的栅格系统如何使用? row ...

  4. vue-cli3使用vue-svg-loader加载svg

    vue-svg-loader Documentation - FAQ webpack loader that lets you use SVG files as Vue components Micr ...

  5. 《Java设计模式》之抽象工厂模式

    场景问题 举个生活中常见的样例--组装电脑.我们在组装电脑的时候.通常须要选择一系列的配件,比方CPU.硬盘.内存.主板.电源.机箱等. 为讨论使用简单点.仅仅考虑选择CPU和主板的问题. 其实,在选 ...

  6. 使用ionic3快速开发webapp(一)

    Ionic可以让我们使用web技术快速构建接近原生体验的跨平台移动应用. 一.安装ionic 1.需要先安装 Node.js(版本8.x之上): 2.安装cordova 和 ionic: $ npm ...

  7. javascript的全局变量 分类: C1_HTML/JS/JQUERY 2014-08-07 11:03 562人阅读 评论(0) 收藏

    javascipt是一门面向对象的编程语言.由于存在一些全局属性及全局函数,因此可以认为存在一个全局变量,这些全局属性及全局函数均是其属性或函数. 在js核心中,并没有定义一个具体的全局变量,因此,j ...

  8. php实现求字符串第一个只出现一次的字符

    php实现求字符串第一个只出现一次的字符 一.总结 很简单的逻辑 1.两个数组,一个存字母,一个存字母出现的次数 二.php实现求字符串第一个只出现一次的字符 题目描述 在一个字符串(1<=字符 ...

  9. js进阶js中支持正则的四个常用字符串函数(search march replace split)

    js进阶js中支持正则的四个常用字符串函数(search march replace split) 一.总结 代码中详细四个函数的用法 search march replace split 二.js进 ...

  10. Android自定义组件系列【5】——进阶实践(1)

    接下来几篇文章将对任老师的博文<可下拉的PinnedHeaderExpandableListView的实现>分步骤来详细实现,来学习一下大神的代码并记录一下. 原文出处:http://bl ...