初探Remoting双向通信(二)
初探Remoting双向通信(二)
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/kkkkkxiaofei/article/details/9167829 </div>
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-cd6c485e8b.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/phoenix/template/css/ck_htmledit_views-cd6c485e8b.css">
<div class="htmledit_views" id="content_views">
二、利用事件实现客户端向服务器通信
接着上一篇,按照我的思路,远程对象中定义的事件在客户端触发,而在服务器端订阅,应该可以成功。现在放弃之前的示例代码,自己重新写一个版本,代码如下:
远程对象:
-
using System;
-
using System.Collections.Generic;
-
using System.Linq;
-
using System.Text;
-
-
namespace Remoting
-
{
-
-
public class RemotingObject:MarshalByRefObject
-
{
-
public delegate void MyDelegate(string msg);
-
public static event MyDelegate myEvent;
-
//触发事件
-
public void TriggerEvent(string msg)
-
{
-
if (myEvent != null)
-
myEvent(msg);
-
}
-
//无限生命周期
-
public override object InitializeLifetimeService()
-
{
-
return null;
-
}
-
}
-
}
服务器:
-
using System;
-
using System.Collections.Generic;
-
using System.ComponentModel;
-
using System.Data;
-
using System.Drawing;
-
using System.Linq;
-
using System.Text;
-
using System.Windows.Forms;
-
using System.Runtime.Remoting;
-
using System.Runtime.Remoting.Channels;
-
using System.Runtime.Remoting.Channels.Tcp;
-
using Remoting;
-
namespace Server
-
{
-
public partial class ServerForm : Form
-
{
-
public ServerForm()
-
{
-
InitializeComponent();
-
StartServer();
-
}
-
//开启服务器
-
public void StartServer()
-
{
-
TcpChannel tcpchannel = new TcpChannel(8080);
-
ChannelServices.RegisterChannel(tcpchannel,false);
-
-
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject),"url",WellKnownObjectMode.Singleton);
-
-
RemotingObject.myEvent += new RemotingObject.MyDelegate(RemotingObject_myEvent);
-
}
-
-
void RemotingObject_myEvent(string msg)
-
{
-
//跨线程调用
-
textBox2.Invoke(new Action<string>(str => { textBox2.Text = str; }), msg);
-
}
-
}
-
}
客户端:
-
using System;
-
using System.Collections.Generic;
-
using System.ComponentModel;
-
using System.Data;
-
using System.Drawing;
-
using System.Linq;
-
using System.Text;
-
using System.Windows.Forms;
-
using System.Runtime.Remoting;
-
using System.Runtime.Remoting.Channels;
-
using System.Runtime.Remoting.Channels.Tcp;
-
using Remoting;
-
-
namespace Client
-
{
-
public partial class ClientForm : Form
-
{
-
RemotingObject obj;
-
public ClientForm()
-
{
-
InitializeComponent();
-
StartClient();
-
}
-
-
private void 发送_Click(object sender, EventArgs e)
-
{
-
obj.TriggerEvent("客户端--" + this.ClientIP() + System.Environment.NewLine + textBox1.Text + System.Environment.NewLine);
-
}
-
//开启客户端
-
public void StartClient()
-
{
-
TcpChannel tcpchannel = new TcpChannel(0);
-
ChannelServices.RegisterChannel(tcpchannel, false);
-
-
obj = (RemotingObject)Activator.GetObject(typeof(RemotingObject), "tcp://localhost:8080/url");
-
-
}
-
//获取本地ip
-
public string ClientIP()
-
{
-
return System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName())[0].ToString();
-
}
-
}
-
}
运行效果如下:
哈哈,如我所愿,利用事件确实实现了客户端与服务器的通信。
可是,这里面有一个小问题:在服务器订阅事件的时候我用到
RemotingObject.myEvent += new RemotingObject.MyDelegate(RemotingObject_myEvent);
这一句其实是我不得已而为之的,为什么这么说的。因为这里myEvent是静态的,只有这样我才可以用RemotingObject.myEvent订阅到事件。但是如果myEvent不是静态的呢?这时候如何去实例化一个对象,并且用"对象.myEvent"来订阅事件呢?如果我在服务器端自己new一个对象,那这个对象肯定和客户端激活得到的对象不是同一个引用。
(注:上面的Demo在此处下载http://download.csdn.net/detail/kkkkkxiaofei/5645629)
带着这个疑问,我找了些资料。有了重大发现。
[SecuritySafeCritical]
public static ObjRef Marshal(MarshalByRefObject Obj, string URI);
来看看官方的解释把:将给定的 System.MarshalByRefObject 转换为具有指定 URI 的 System.Runtime.Remoting.ObjRef 类的实例。
看到实例两个字我就激动了, 这里我的RemotingObject类就继承了System.MarshalByRefObject。这个ObjRef 类是做什么的?如果将其转换为ObjRef 类的实例又能怎么样呢?
再来看看ObjRef 吧。
ObjRef :存储生成代理以与远程对象通信所需要的所有信息。
有了上面的概念,我又有了点思路了:
之前客户端(RemotingObject)Activator.GetObject(typeof(RemotingObject), "tcp://localhost:8080/url")得到的这个对象,是服务器注册的RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject),"url",WellKnownObjectMode.Singleton)这个对象的引用。在服务器端并不能获取这个对象。那如果我在服务器端显示创建一个对象,然后让客户端刚好能获取这个引用不就行了么。Marshal方法不就是显示生成服务器端的RemotingObject对象的代理么,客户端激活的代码已然不变,利用ip地址和url就能找到这个对象,这样2个程序域中的2个对象其实就是同一个引用。这么一来,就可以解决掉事件只能是静态的尴尬局面了,好了是时候验证我的想法了。代码如下,
远程对象:
-
using System;
-
using System.Collections.Generic;
-
using System.Linq;
-
using System.Text;
-
-
namespace Remoting
-
{
-
public class RemotingObject:MarshalByRefObject
-
{
-
public delegate void MyDelegate(string msg);
-
public event MyDelegate myEvent;
-
//触发事件
-
public void TriggerEvent(string msg)
-
{
-
if (myEvent != null)
-
myEvent(msg);
-
}
-
//无限生命周期
-
public override object InitializeLifetimeService()
-
{
-
return null;
-
}
-
}
-
}
客户端:
-
using System;
-
using System.Collections.Generic;
-
using System.ComponentModel;
-
using System.Data;
-
using System.Drawing;
-
using System.Linq;
-
using System.Text;
-
using System.Windows.Forms;
-
using System.Runtime.Remoting;
-
using System.Runtime.Remoting.Channels;
-
using System.Runtime.Remoting.Channels.Tcp;
-
using Remoting;
-
-
namespace Client
-
{
-
public partial class ClientForm : Form
-
{
-
RemotingObject obj;
-
public ClientForm()
-
{
-
InitializeComponent();
-
StartClient();
-
}
-
-
private void 发送_Click(object sender, EventArgs e)
-
{
-
obj.TriggerEvent("客户端--" + this.ClientIP() + System.Environment.NewLine + textBox1.Text + System.Environment.NewLine);
-
}
-
//开启客户端
-
public void StartClient()
-
{
-
TcpChannel tcpchannel = new TcpChannel(0);
-
ChannelServices.RegisterChannel(tcpchannel, false);
-
-
obj = (RemotingObject)Activator.GetObject(typeof(RemotingObject), "tcp://localhost:8080/url");
-
-
}
-
//获取本地ip
-
public string ClientIP()
-
{
-
return System.Net.Dns.GetHostAddresses(System.Net.Dns.GetHostName())[0].ToString();
-
}
-
}
-
}
服务器:
-
using System;
-
using System.Collections.Generic;
-
using System.ComponentModel;
-
using System.Data;
-
using System.Drawing;
-
using System.Linq;
-
using System.Text;
-
using System.Windows.Forms;
-
using System.Runtime.Remoting;
-
using System.Runtime.Remoting.Channels;
-
using System.Runtime.Remoting.Channels.Tcp;
-
using Remoting;
-
namespace Server
-
{
-
public partial class ServerForm : Form
-
{
-
RemotingObject marshal_obj;
-
public ServerForm()
-
{
-
InitializeComponent();
-
StartServer();
-
}
-
//开启服务器
-
public void StartServer()
-
{
-
TcpChannel tcpchannel = new TcpChannel(8080);
-
ChannelServices.RegisterChannel(tcpchannel,false);
-
-
//RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingObject),"url",WellKnownObjectMode.Singleton);
-
-
marshal_obj = new RemotingObject();
-
ObjRef objRef = RemotingServices.Marshal(marshal_obj, "url");
-
marshal_obj.myEvent += new RemotingObject.MyDelegate(RemotingObject_myEvent);
-
}
-
-
void RemotingObject_myEvent(string msg)
-
{
-
//跨线程调用
-
textBox2.Invoke(new Action<string>(str => { textBox2.Text = str; }), msg);
-
}
-
}
-
}
运行结果很乐观,如期所料
看来用Marshal方法确实可以让服务器和客户端都有一份远程对象的引用,咦,那这么说,服务器岂不是也可以主动触发事件,然后让客户端来绑定,这样就能实现服务器向客户端通信。哈哈,离我的项目需求又近了一步,不错不错,下篇试试实现这个问题。
(注:上面的Demo在此处下载http://download.csdn.net/detail/kkkkkxiaofei/5646103)
初探Remoting双向通信(二)的更多相关文章
- 初探Remoting双向通信(四)
原 初探Remoting双向通信(四) 2013年06月26日 11:11:32 喜欢特别冷的冬天下着雪 阅读数 2632 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- 初探Remoting双向通信(三)
原 初探Remoting双向通信(三) 2013年06月25日 17:51:08 喜欢特别冷的冬天下着雪 阅读数 4741 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- 初探remoting双向通信(一)
原 初探remoting双向通信(一) 2013年06月24日 15:47:07 喜欢特别冷的冬天下着雪 阅读数 4389 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blo ...
- 初探JavaScript(二)——JS如何动态操控HTML
除去五一三天,我已经和<JavaScript Dom编程艺术>磨合了六天,第一印象很好.慢慢的,我发现这是一块排骨,除了肉还有骨头.遇到不解的地方就会多看几遍,实在不懂的先跳过,毕竟,初次 ...
- C# 实现Remoting双向通信
本篇文章主要介绍了C# 实现Remoting双向通信,.Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象来实现通信的 闲来无事想玩玩双向通 ...
- C# Remoting双向通信
闲来无事想玩玩双向通信,实现类似QQ的互发消息的功能.于是乎开始学习.Net Remoting. .Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为 ...
- MongoDB初探系列之二:认识MongoDB提供的一些经常使用工具
在初探一中,我们已经能够顺利的将MongoDB在我们自己的机器上跑起来了. 可是在其bin文件夹以下另一些我们不熟知的工具.接下来,将介绍一下各个小工具的用途以及初探一中MongoDB在data文件夹 ...
- javascript --- 原型初探七日谈(二)
扩展内建对象: 在javascript中,内建对象的构造函数都是可以通过其原型来进行扩展的.这意味着我们可以做一些事情,例如我们要往数组原型中添加一个新方法,就可以在其所有的数组中使用,下面我们来试试 ...
- 跟我一起学WCF(2)——利用.NET Remoting技术开发分布式应用
一.引言 上一篇博文分享了消息队列(MSMQ)技术来实现分布式应用,在这篇博文继续分享下.NET平台下另一种分布式技术——.NET Remoting. 二..NET Remoting 介绍 2.1 . ...
随机推荐
- BZOJ 4765(分块+树状数组)
题面 传送门 "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些 .普通计算机能计算数列区间和,而普通计算姬能计算树中子树和.更 ...
- 记一些经常用到的linux命令
记一些经常用到的linux命令,备忘用 用清华源pip: pip install django==1.11 tensorflow==1.4.0 keras==2.0.6 -i https://pyp ...
- object in depth
创建和修改属性 创建对象 const myObject = {}; //字面量表示法 const myObject = new Object(); //Object() 构造函数 修改属性 ---- ...
- SET - 改变运行时参数
樊伟胜SYNOPSIS SET [ SESSION | LOCAL ] name { TO | = } { value | 'value' | DEFAULT } SET [ SESSION | LO ...
- ubuntu下安装chrome谷歌浏览器
百度“chrome”然后登录谷歌浏览器官网下载deb包 cd到下载的目录下 sudo dpkg -i google-chrome*; 提示缺少依赖包,打入如下命令 sudo apt-get -f in ...
- ARM-LINUX学习记录
1:调用C语言函数之前会有一段汇编代码在前面执行来完成软硬件方面的初始化.比如:关闭看门狗:初始化时钟:设置堆栈:调用main函数等.在学习51单片机时候这些操作是由开发环境(如KEIL)在编译C代码 ...
- 使用IntelliJ IDEA 15和Maven创建Java Web项目(转)
转自:https://blog.csdn.net/myarrow/article/details/50824793 1. Maven简介 相对于传统的项目,Maven 下管理和构建的项目真的非常好用和 ...
- java命令-jstat/ javap
jstat命令对应用程序资源和性能进行实时监控 常用参数列举如下: 1. jstat -class pid 显示加载class的数量.所占空间.所耗时间等信息 2.jstat -compiler pi ...
- python基础--逻辑运算
#and or not#and 且 :两边都为真才是真#or 或:一个真就是真(一真为真)#ont 非:相反#优先级:1.not>and>or#同一优先级由左向右以此计算!#列子:prin ...
- vue img标签用法
:符号是v-bind的缩写 服务器图片路径和请求本地路径 <img class="v-step-0" id="avatar" :src="myP ...