作为微软分布式技术之一的.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 <? xml version = " 1.0 " encoding = " utf-8 " ?> 2 < configuration > 3 < system.runtime.remoting > 4 < application > 5 < channels > 6 < channel ref = " http " port = " 0 " > 7 < serverProviders > 8 < provider ref = " wsdl " ></ provider > 9 < formatter ref = " binary " typeFilterLevel = " Full " ></ formatter > 10 </ serverProviders > 11 < clientProviders > 12 < formatter ref = " binary " ></ formatter > 13 </ clientProviders > 14 </ channel > 15 </ channels > 16 </ application > 17 </ system.runtime.remoting > 18 </ 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
{
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/