.Net Remoting的双向通信和Windows Service的宿主服务
原文:.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的宿主服务的更多相关文章
- windows service自动重启服务
服务一般都能正常的运行,但有时候也会有一些假死现象,比如公司有一考勤服务就因为依赖于硬件厂家的api, 但厂家api运行一段时间后会默名的假死,引起整个服务假死,因为这一假死现象具有不确定性,所以不太 ...
- windows service宿主web api使用"依赖注入"和“控制反转”的技术实践
前言 自从几年前抛弃wcf,使用web api 来做服务器端开发之后,就不再迷惑了.但是因为本来从事传统行业管理软件开发,一般都以分布式应用开发为主.纯BS还是比较少,于是比较喜欢用windows s ...
- 关于Windows Service的一个编写技巧
写过Windows Service的朋友都知道服务是不可以直接在vs里面启动调试,我们必须修改Program.cs文件来达到我们调试的目的,等服务调试好了以后还要把代码改回来,显非常的不方便,在这里为 ...
- 从Web Service和Remoting Service引出WCF服务
本篇先通过Web Service和Remoting Service创建服务,抛砖引玉,再体验WCF服务.首先一些基本面: 什么是WCF? Windows Communication Foundatio ...
- quartz.net结合Topshelf实现windows service服务托管的作业调度框架
topshelf可以很简单方便的实现windows service服务,详见我的一篇博客的介绍 http://www.cnblogs.com/xiaopotian/articles/5428361.h ...
- windows Service 之调试过程(附加到进程里调试,而且启动时间不能超过30秒)
最近第一次用C#写了一个windows service ,其实实现的内容比较简单.就是启动remoting 连接,但是调试相对初次写windws service 的我来说,比较烦.没有经验,而且没办法 ...
- C#创建、安装、卸载、调试Windows Service(Windows 服务)的简单教程
前言:Microsoft Windows 服务能够创建在它们自己的 Windows 会话中可长时间运行的可执行应用程序.这些服务可以在计算机启动时自动启动,可以暂停和重新启动而且不显示任何用户界面.这 ...
- 如何利用mono把.net windows service程序迁移到linux上
How to migrate a .NET Windows Service application to Linux using mono? 写在最前:之所以用要把windows程序迁移到Linux上 ...
- 如何托管ASP.NET Core应用到Windows Service中
(此文章同时发表在本人微信公众号"dotNET开发经验谈",欢迎右边二维码来关注.) 题记:正在构思一个中间件的设计,考虑是否既可以使用最新的技术,也可以兼顾传统的部署模式.所以有 ...
随机推荐
- Android(Lollipop/5.0) Material Design(四) 创建列表和卡片
Material Design系列 Android(Lollipop/5.0)Material Design(一) 简单介绍 Android(Lollipop/5.0)Material Design( ...
- 三国武将查询系统 //Java 訪问 数据库
import java.awt.*; import javax.swing.*; import java.awt.event.ActionListener; import java.awt.event ...
- MFC注册窗口类以及FindWindow按窗口类名查询(避免用#32770获取窗口句柄)
呵呵,最近在研究SendMessage函数,其中需要用到m_hWnd,之后延伸着又尝试获得窗口的句柄,于是遇到了FindWindow函数,原型如下: HWND FindWindow ( LPCSTR ...
- AE中地图查询方式
樱木 原文 AE中地图查询方式 地图查询主要有两种查询:空间查询和属性查询 所用到知识点: 1 Cursor(游标)对象 本质上是一个指向数据的指针,本身不包含数据内容,提供一个连接到ROW对象或者 ...
- blob-照片转换与展示
File转java.sql.Blob(照片)Struts2 public Blob photos(File zp) { Blob photo=null; try { FileInputStream f ...
- perl对比两个文件的行
perl对比两个文件的行 对比两个文件的各行,得到A与B相同的行/A与B不相同的行 主要功能 得到相同行 得到A中包含,B不包含的行 得到B中包含,A中不包含的行 具体执行情况 Perl代码 #!/u ...
- 我的嵌入式Qt开发第一课——基于BBB和hmc5843三轴电子罗盘
几次想照着课本系统地学习Qt,但我发现还是有详细问题驱动时学习比較快. 于是我给自己设定了这个任务: 读取HMC5843的三轴磁场强度值,计算出角度,并把角度用直观形式显示在图形界面上. 这里面涉及到 ...
- #308 (div.2) B. Vanya and Books
1.题目描写叙述:点击打开链接 2.解题思路:本题要求统计数位的个数,简单的试验一下发现有例如以下规律:一个n位数的个数有9*(10^n)个.因此全部n位数的数位是n*9*(10^n)个.因此能够利用 ...
- jquery-4 完整表单验证实例
jquery-4 完整表单验证实例 一.总结 一句话总结:在form的jquery对象中返回false即可终止表单提交. 1.验证的显示错误消息如何布局? 开始时隐藏,出现错误后显示 10 .erro ...
- windows下python安装uwsgi
1.使用pip安装 pip install uwsgi 报错:os没有uname() 解决: 定位到uwsgiconfig.py文件中,首先import platform后,将os.unam()都改为 ...