zoukankan
html css js c++ java
[Remoting专题系列] 十一:事件 【转】
在 Remoting 中使用 Event 主要是为了实现 CallBack 机制,让服务器在接收到某个
"
消息
"
时,主动调用某个或多个客户端的方法。
我们先看一个例子。
using
System;
using
System.Collections;
using
System.Collections.Generic;
using
System.Reflection;
using
System.Runtime.Serialization.Formatters;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
namespace
Learn.Library.Remoting
{
/**/
///
<summary>
///
委托类型
///
</summary>
public
delegate
void
TestHandler();
/**/
///
<summary>
///
远程类型
///
</summary>
public
class
Data : MarshalByRefObject
{
public
TestHandler OnTest;
public
void
Test()
{
Console.WriteLine(
"
Test
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
if
(OnTest
!=
null
) OnTest();
}
}
public
class
RemotingTest2
{
/**/
///
<summary>
///
服务器端代码
///
</summary>
static
void
Server()
{
AppDomain server
=
AppDomain.CreateDomain(
"
server
"
);
server.DoCallBack(
delegate
{
BinaryServerFormatterSinkProvider bin
=
new
BinaryServerFormatterSinkProvider();
bin.TypeFilterLevel
=
TypeFilterLevel.Full;
TcpServerChannel channel
=
new
TcpServerChannel(
"
server
"
,
801
, bin);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof
(Data),
"
data
"
,
WellKnownObjectMode.Singleton);
}
);
}
/**/
///
<summary>
///
客户端代码
///
</summary>
static
void
Client()
{
TcpClientChannel channel
=
new
TcpClientChannel();
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownClientType(
typeof
(Data),
"
tcp://localhost:801/data
"
);
Data data
=
new
Data();
data.OnTest
+=
delegate
{
Console.WriteLine(
"
OnTest
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
}
;
data.Test();
}
static
void
Main()
{
Server();
Client();
}
}
}
输出:
Test
(AppDomain:server)
OnTest
(AppDomain:server)
运行结果表明客户端事件方法 OnTest 被顺利执行。只不过结果有点问题,OnTest 是在服务器程序域内执行,这显然和我们设想服务器去通知客户端有所出入。这种方式实质上是将客户端委托方法一起序列化为消息传递到服务器端,然后在服务器应用程序域被执行,因此客户端是无法接收到所谓
"
回调消息
"
的。
要实现我们所需要的 Remoting Event,需要做如下步骤:
1
. 采取所谓 Duplex 方式。也就是说在客户端和服务器同时启用 ServerChannel 和 ClientChannel,因此我们需要使用 HttpChannel 或 TcpChannel。
2
. 客户端事件方法应该是一个继承自 MarshalByRefObject 类型的实例方法。因为服务器是通过创建客户端的 MBR SAO 对象来实现回调的。
3
. 缺省情况下,Delegate 无法被序列化,因此我们需要将服务器的 Formatter.TypeFilterLevel 设置为 Full。
修改后的代码。
using
System;
using
System.Collections;
using
System.Collections.Generic;
using
System.Reflection;
using
System.Runtime.Serialization.Formatters;
using
System.Runtime.Serialization.Formatters.Binary;
using
System.Runtime.Remoting;
using
System.Runtime.Remoting.Channels;
using
System.Runtime.Remoting.Channels.Tcp;
namespace
Learn.Library.Remoting
{
/**/
///
<summary>
///
委托类型
///
</summary>
public
delegate
void
TestHandler();
/**/
///
<summary>
///
远程类型
///
</summary>
public
class
Data : MarshalByRefObject
{
public
TestHandler OnTest;
public
void
Test()
{
Console.WriteLine(
"
Test
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
if
(OnTest
!=
null
) OnTest();
}
}
/**/
///
<summary>
///
客户端远程类型
///
</summary>
public
class
ClientData : MarshalByRefObject
{
public
void
OnTestMethod()
{
Console.WriteLine(
"
Test
(AppDomain:{0})
"
, AppDomain.CurrentDomain.FriendlyName);
}
}
public
class
RemotingTest2
{
/**/
///
<summary>
///
服务器端代码
///
</summary>
static
void
Server()
{
AppDomain server
=
AppDomain.CreateDomain(
"
server
"
);
server.DoCallBack(
delegate
{
BinaryClientFormatterSinkProvider cbin
=
new
BinaryClientFormatterSinkProvider();
BinaryServerFormatterSinkProvider sbin
=
new
BinaryServerFormatterSinkProvider();
sbin.TypeFilterLevel
=
TypeFilterLevel.Full;
Hashtable properties
=
new
Hashtable();
properties[
"
port
"
]
=
801
;
TcpChannel channel
=
new
TcpChannel(properties, cbin, sbin);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownServiceType(
typeof
(Data),
"
data
"
,
WellKnownObjectMode.Singleton);
}
);
}
/**/
///
<summary>
///
客户端代码
///
</summary>
static
void
Client()
{
TcpChannel channel
=
new
TcpChannel(
802
);
ChannelServices.RegisterChannel(channel,
false
);
RemotingConfiguration.RegisterWellKnownClientType(
typeof
(Data),
"
tcp://localhost:801/data
"
);
Data data
=
new
Data();
data.OnTest
+=
new
ClientData().OnTestMethod;
data.Test();
}
static
void
Main()
{
Server();
Client();
}
}
}
查看全文
相关阅读:
符号修饰与函数签名、extern “C”
WinInet单线程断点续传下载
关掉"离开模式“,解决计算机无法进入睡眠状态
链接库——动态链接库
Google开源项目风格指南——类
使用CURL读取HTTP数据到字符串或者文件中
Wininet多线程断点续传下载
contains
[转]在linux下如何使用Makefile对fortran程序进行编译
【转】一些解决变态数学公式的算法地址
原文地址:https://www.cnblogs.com/cxd4321/p/888804.html
最新文章
自定义页码页码
GO
生意就是这样做成的 GO
Linux 平台下 MySQL 5.5 安装 说明 与 示例
苹果系统有病毒吗?
XMLHelper.cs
SQL des加密算法存储过程
C#委托与事件讲解(二)
C#委托与事件讲解(一)
Android使用sqllite实例
C#委托与事件讲解(序言)
热门文章
.net使用sqllite实例
SQL2005中的事务与锁定
Iframe自适应高度
C#桌面图标弹出提示
如何创建数据库架构
WordPress 固定链接变更后的 htaccess 301转向规则
C#迅雷七窗体特效,使用DWM实现Aero Glass效果
获取文件详细信息的方法
有关调用约定(调用惯例)
更改windows sdk 7.1 command prompt 默认路径(不要随便更改)
Copyright © 2011-2022 走看看