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();
}
}
}
查看全文
相关阅读:
记一次在线阅卷系统设计开发总结
卡座录音经验汇总
TEAC 6030S 统调
空白磁带SONY TDK 万胜,3大品牌空白磁带,入门必读
cnetos 7 mysql 从data还原数据库
java的BigDecimal比较大小
nginx配置静态访问txt文件
小程序筛选
买分产整合
开窗函数
原文地址:https://www.cnblogs.com/cxd4321/p/888804.html
最新文章
有趣的API接口【收集】
基于docker的深度学习开发环境
shell读取config.ini文件
golang FastHttp 使用
apt下载离线安装包
defer的用法
golang 内存和cpu优化
golang字段串压缩和解压缩
fastDFS安装
FastDFS入门
热门文章
kafkatools加密连接
Centos 网卡链路聚合
css设置图片根据最大边自适应
Vue 监听鼠标左键 鼠标右键以及鼠标中键修饰符click.left&contextmenu&click.middle
记一次win10打开文件夹和右键持续卡顿的被动解决
ApiPost进阶教程(1) — 在ApiPost中使用脚本
作为Java开发工程师,如何高效优雅地编写接口文档
还在用Postman?来,花2分钟体验下ApiPost的魅力
比POSTMAN更好用!在国产接口调试工具APIPOST中使用Mock
利用课间10分钟,打造一个恶劣天气实时预警系统
Copyright © 2011-2022 走看看