梦琪小生 通过本文主要向大家介绍了马桶c的个人空间,c语言,欲情 c max,维生素c,crh2c等相关知识,希望对您有所帮助,也希望大家支持linkedu.com www.linkedu.com
闲来无事想玩玩双向通信,实现类似QQ的互发消息的功能。于是乎开始学习.Net Remoting.
.Net Remoting 是由客户端通过Remoting,访问通道以获得服务端对象,再通过代理解析为客户端对象来实现通信的。也就是说对象是由服务端创建的。
先上代码
首先是ICommand库
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ICommand { public interface IRemotingObject { event SendHandler ClientToServer; event ReceiveHandler ServerToClient; event UserChangedHandler Login; event UserChangedHandler Exit; /// <summary> /// 加法运算 /// </summary> /// <param name="x1">参数1</param> /// <param name="x2">参数2</param> /// <returns></returns> string SUM(int x1, int x2); /// <summary> /// 获取服务端事件列表 /// </summary> Delegate[] GetServerEventList(); /// <summary> /// 发送消息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> void ToServer(object info, string toName); /// <summary> /// 接受信息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> void ToClient(object info, string toName); void ToLogin(string name); void ToExit(string name); } /// <summary> /// 客户端发送消息 /// </summary> /// <param name="info">信息</param> /// <param name="toName">发送给谁,""表示所有人,null表示没有接收服务器自己接收,其他表示指定某人</param> public delegate void SendHandler(object info, string toName); /// <summary> /// 客户端接收消息 /// </summary> /// <param name="info">信息</param> /// <param name="toName">发送给谁,""表示所有人,null表示没有接收服务器自己接收,其他表示指定某人</param> public delegate void ReceiveHandler(object info, string toName); /// <summary> /// 用户信息事件 /// </summary> /// <param name="name">用户名</param> public delegate void UserChangedHandler(string name); }</div>
using System; using System.Collections.Generic; using System.Linq; using System.Text; namespace ICommand { public class SwapObject : MarshalByRefObject { public event ReceiveHandler SwapServerToClient { add { _receive += value; } remove { _receive -= value; } } /// <summary> /// 接受信息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> public void ToClient(object info, string toName) { if (_receive != null) _receive(info, toName); } //无限生命周期 public override object InitializeLifetimeService() { return null; } private ReceiveHandler _receive; } }</div>
第一个类就是定义一些接口,和一些委托,没有实质性的东西。
第二个类是定义了上一个接口类中的ToClient的事件和方法,作用之后会讲到。
然后就是集成ICommand接口的实质性的数据类
using System; using System.Collections.Generic; using System.Linq; using System.Text; using ICommand; namespace NetRemoting { public class RemotingObject : MarshalByRefObject, IRemotingObject { /// <summary> /// 发送事件 /// </summary> public event SendHandler ClientToServer { add { _send += value; } remove { _send -= value; } } /// <summary> /// 接收消息事件 /// </summary> public event ReceiveHandler ServerToClient; /// <summary> /// 发送事件 /// </summary> public event UserChangedHandler Login { add { _login += value; } remove { _login -= value; } } /// <summary> /// 发送事件 /// </summary> public event UserChangedHandler Exit { add { _exit += value; } remove { _exit -= value; } } /// <summary> /// 加法运算 /// </summary> /// <param name="x1">参数1</param> /// <param name="x2">参数2</param> /// <returns></returns> public string SUM(int x1, int x2) { return x1 + "+" + x2 + "=" + (x1 + x2); } /// <summary> /// 绑定服务端向客户端发送消息的事件方法 /// </summary> /// <param name="receive">接收事件</param> public Delegate[] GetServerEventList() { return this.ServerToClient.GetInvocationList(); } /// <summary> /// 发送消息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> public void ToServer(object info, string toName) { if (_send != null) _send(info, toName); } /// <summary> /// 接收消息 /// </summary> /// <param name="info"></param> /// <param name="toName"></param> public void ToClient(object info, string toName) { if (_receive != null) _receive(info, toName); } /// <summary> /// 登录 /// </summary> /// <param name="name">用户名</param> public void ToLogin(string name) { if (!_nameHash.Contains(name)) { _nameHash.Add(name); if (_login != null) _login(name); } else { throw new Exception("用户已存在"); } } /// <summary> /// 退出 /// </summary> /// <param name="name">用户名</param> public void ToExit(string name) { if (_nameHash.Contains(name)) { _nameHash.Remove(name); if (_exit != null) _exit(name); } } private SendHandler _send; private ReceiveHandler _receive; private UserChangedHandler _login; private UserChangedHandler _exit; private HashSet<string> _nameHash = new HashSet<string>(); } }</div>
该类集成了MarshalByRefObject
由于Remoting传递的对象是以引用的方式,因此所传递的远程对象类必须继承MarshalByRefObject。MSDN对MarshalByRefObject的说明是:MarshalByRefObject 是那些通过使用代理交换消息来跨越应用程序域边界进行通信的对象的基类。不是从 MarshalByRefObject 继承的对象会以隐式方式按值封送。当远程应用程序引用一个按值封送的对象时,将跨越远程处理边界传递该对象的副本。因为您希望使用代理方法而不是副本方法进行通信,因此需要继承MarshallByRefObject。
该类主要是定义了一些方法用于客户端触发事件,ToServer,ToClient,ToLogin,ToExit以及一些事件,客户端发向服务端的事件,和服务端发向客户端的事件。
_nameHash 只是记录有哪些用户登录了。
接下去就是客户端和服务端了。
首先服务端:
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.Http; using NetRemoting; using System.Collections; using System.Runtime.Serialization.Formatters; using ICommand; namespace NetRemotingServer { public partial class Server : Form { public Server() { InitializeComponent(); Initialize(); } /// <summary> /// 注册通道 /// </summary> /// <param name="sender"></param> /// <param name="e"></para