原文:.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 {

     /// <summary>

     /// 服务器端回调接口

     /// </summary>

     public interface IChatCallback

     {

         /// <summary>

         /// 回调方法,显示聊天消息

         /// </summary>

         /// <param name="message"></param>

         void ShowMessage(string message);

     }

 }

接口定义好了,现在可以提供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

             callBack.ShowMessage(message);

         }

     }

 }

通常开发.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="">

           <serverProviders>

             <provider ref="wsdl"></provider>

             <formatter ref="binary" typeFilterLevel="Full"></formatter>

           </serverProviders>

           <clientProviders>

             <formatter ref="binary"></formatter>

           </clientProviders>

         </channel>

       </channels>

     </application>

   </system.runtime.remoting>

 </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();

         }

     }

 }

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

Code

 1 <?xml version="1.0" encoding="utf-8" ?>

 2 <configuration>

 3   <system.runtime.remoting>

 4     <application>

 5       <channels>

 6         <channel ref="http" port="">

 7           <serverProviders>

 8             <provider ref="wsdl"></provider>

 9             <formatter ref="binary" typeFilterLevel="Full"></formatter>

           </serverProviders>

           <clientProviders>

             <formatter ref="binary"></formatter>

           </clientProviders>

         </channel>

       </channels>

     </application>

   </system.runtime.remoting>

 </configuration>

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

 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         {

             RemotingConfiguration.Configure("ChatRoom.Client.exe.config", false);

             proxy  = (IDuplexChat)Activator.GetObject(typeof(IDuplexChat), "http://localhost:8080/ChatRoom/ChatRoomURL");

 

             message = Console.ReadLine();

             SendMessage(message);

         }

 

         private static void SendMessage(string message)

         {

             proxy.SendMessage(message, new ChatRoomCallBackHandler());

 

             message = Console.ReadLine();

             if (message != "exit")

             {

                 SendMessage(message);

             }

         }

     }

 }

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

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

 protected override void OnStart(string[] args)

 {

     RemotingConfiguration.Configure("ChatRoom.WinServiceHost.exe.config", false);

 }

光这样是不能完成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. [AngularFire 2] Joins in Firebase

    Lets see how to query Firebase. First thing, when we do query, 'index' will always help, for both SQ ...

  2. WCF REST 基础教程

    概述 Representational State Transfer(REST)是Roy Fielding博士在2000年他的博士论文中提出来的一种软件架构风格. 因此REST是设计风格而不是标准,R ...

  3. php protected 类型如何获取

    感谢 https://blog.csdn.net/m0_38092942/article/details/81354184 比如对象如下 object(App\User)#265 (28) { [&q ...

  4. ZOJ-1649 Rescue BFS (HDU 1242)

    看题传送门: ZOJ http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=1649 HDU http://acm.hdu.edu. ...

  5. 王立平--eclipse本地配置svn

    1.下载 watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdTAxMzQyNTUyNw==/font/5a6L5L2T/fontsize/400/fill/I ...

  6. jQuery 中 is() 函数常见使用方法

    依据选择器.DOM元素或 jQuery 对象来检測匹配元素集合.假设当中至少有一个元素符合这个给定的表达式就返回true. 假设没有元素符合,或者表达式无效.都返回'false'. '''注意:''' ...

  7. Multivariate Linear Regression

    Multiple Features Linear regression with multiple variables is also known as "multivariate line ...

  8. css 控制行数 多出的省略

    <html lang="en"> <head> <meta charset="UTF-8"> <title>Do ...

  9. 使用SQLiteHelper创建数据库并插入数据 分类: H1_ANDROID 2013-11-05 22:44 1398人阅读 评论(0) 收藏

    参考<疯狂android讲义>8.4节P424 1.获取SQLiteDatabase实例有2种方法,一是直接new SQLiteDatabase(),另一种使用SQLiteHelper.一 ...

  10. text输入框改变事件

    前端页面开发的很多情况下都需要实时监听文本框输入,比如腾讯微博编写140字的微博时输入框hu9i动态显示还可以输入的字数.过去一般都使用onchange/onkeyup/onkeypress/onke ...