急需解决啊,Remoting 事件注册不了

miyoo 2008-09-08 03:46:31
一、远程接口定义

namespace KnownObjects
{
/// <summary>
/// 报警结构体
/// </summary>
[Serializable]
public struct ALARM
{
public string ipAddress;
public string hostName;
public string alarmTime;
public string alarmMess;

}
/// <summary>
/// 报警客户端
/// </summary>
public interface IAlarmClient
{
/// <summary>
/// 消息反馈
/// </summary>
/// <param name="message">A message.</param>
object ReceiveMessage(ALARM message);
}

/// <summary>
/// 报警消息通用方法
/// </summary>
public interface IAlarmRoom
{
/// <summary>
/// 发送报警信息到所有客户端
/// </summary>
/// <param name="message">Message to send.</param>
void SendMessage(ALARM message);

/// <summary>
/// 注册报警客户端
/// </summary>
/// <param name="iAlarmClient"></param>
void AttachClient(IAlarmClient iAlarmClient);
}
}


二、客户接收端


namespace ReceiveClient
{

/// <summary>
/// ChatClient demostrates simple client application.
/// </summary>
public class ReceiveAlarm : MarshalByRefObject, IAlarmClient
{
public class AlarmMsgEventArgs : EventArgs
{

// 1. Type defining information passed to receivers of the event
public AlarmMsgEventArgs(String ip, String hostname, String mess, String time)
{
this.ip = ip;
this.hostname = hostname;
this.mess = mess;
this.time = time;
}
public readonly String ip, hostname,mess,time;
}
//报警消息委托
public delegate void AlarmMsgEventHandler(Object sender,AlarmMsgEventArgs args);
//报警消息事件
public event AlarmMsgEventHandler AlarmMsg;
//负责通知事件的登记对象
protected virtual void OnAlarmMsg(AlarmMsgEventArgs e)
{

// Has any objects registered interest with our event?
if (AlarmMsg != null)
{
// Yes, notify all the objects
AlarmMsg(this, e);
}
}

private IAlarmRoom iAlarmRoom;

/// <summary>
/// Sigleton instance.
/// </summary>
public static ReceiveAlarm Instance = new ReceiveAlarm();

public ReceiveAlarm()
{
}
//连接服务器
public bool InitRemoting()
{
try
{
System.Configuration.ConfigurationSettings.GetConfig("DNS");
GlobalEventContainer.GenuineChannelsGlobalEvent += new GenuineChannelsGlobalEventHandler(GenuineChannelsEventHandler);
RemotingConfiguration.Configure("Client.exe.config");
iAlarmRoom = (IAlarmRoom)Activator.GetObject(typeof(IAlarmRoom), "gtcp://127.0.0.1:8737/ChatRoom.rem");
iAlarmRoom.AttachClient(ReceiveAlarm.Instance);


}
catch (System.Exception e)
{
Console.WriteLine("异常错误:服务器未启动?");
return false;
}

return true;
}

public static void GenuineChannelsEventHandler(object sender, GlobalEventArgs e)
{
Console.WriteLine("Global event: {0}, Url: {1}, Exception: {2}", e.EventType, e.Url, e.SourceException);
if (e.EventType == GlobalEventTypes.GTcpConnectionClosed &&
e.SourceException is OperationException &&
((OperationException)e.SourceException).OperationErrorMessage.ErrorIdentifier.IndexOf("ServerHasBeenRestarted") > -1)
{
// server has been restarted so we have to register our listener again
IAlarmRoom iAlarmRoom = (IAlarmRoom)Activator.GetObject(typeof(IAlarmRoom), "gtcp://127.0.0.1:8737/ChatRoom.rem");
iAlarmRoom.AttachClient(ReceiveAlarm.Instance);
}
}

/// <summary>
/// 接收到报警信息.实现了远程接口的方法
/// </summary>
/// <param name="message">The message.</param>
public object ReceiveMessage(ALARM message)
{
///测试,接收到消息后触发本地自定义事件,但是有问题,AlarmMsg=null;测试类在后面
AlarmMsgEventArgs e = new AlarmMsgEventArgs(message.ipAddress, message.hostName, message.alarmMess, message.alarmTime);
OnAlarmMsg(e);
//这里能够打印出远程传来的信息
Console.WriteLine("{0},{1},{2},{3}",message.ipAddress, message.hostName, message.alarmMess, message.alarmTime);

return null;
}

public void ArrivingMsg(string ip, string hostname, string mess, string time)
{
AlarmMsgEventArgs e = new AlarmMsgEventArgs(ip, hostname, mess, time);
OnAlarmMsg(e);
//Console.WriteLine("Msg...(AppDomain:{0} {1})", AppDomain.CurrentDomain.FriendlyName,mess);
}

/// <summary>
/// This is to insure that when created as a Singleton, the first instance never dies,
/// regardless of the expired time.
/// </summary>
/// <returns></returns>
public override object InitializeLifetimeService()
{
return null;
}
}
}


三、测试类


namespace ReceiveClient
{
public class Program
{
static void Main(string[] args)
{
ReceiveAlarm receive = new ReceiveAlarm();
receive.InitRemoting();
Receiver test = new Receiver(receive);
Console.ReadLine();
}
}
//测试类
//ReceiveAlarm对象以参数形式传递给测试类,
public class Receiver
{
public Receiver(ReceiveAlarm mm)
{
//注册事件
mm.AlarmMsg += new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);
}

private void RecMsg(Object sender, ReceiveAlarm.AlarmMsgEventArgs e)
{
Console.WriteLine(" Receiving message:");
Console.WriteLine(" IP: {0}\n HostName: {1}\n Message: {2}\n Time {3}\n", e.ip, e.hostname, e.mess, e.time);
}

public void UnRegister(ReceiveAlarm mm)
{
mm.AlarmMsg -= new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);
}
}
}


四、问题
这是个Remoting 的广播事件,ReceiveAlarm能够注册服务器,并接收到信息(继承IAlarmClient),
我的目的是,在接收到了远程消息后,让他触发我自定义的事件,这样在GUI界面中就可以显示报警信息。
Receiver类测试接收类,注册事件,但触发不了?
...全文
150 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
wolf_life 2008-09-09
  • 打赏
  • 举报
回复
跟一下,,不知道你的问题出在哪里,,要是从服务器收到消息了。。触发事件,加上我说的对方就可以了。如果是别的对方。就再找找原因吧。。望尽快解决吧。。啊哈哈
miyoo 2008-09-09
  • 打赏
  • 举报
回复
不是你们说的那样,还是没有访问到触发的报警实例,所以没有注册到,,还是要感谢大家!
wolf_life 2008-09-09
  • 打赏
  • 举报
回复
mm.AlarmMsg(this, e)
wolf_life 2008-09-09
  • 打赏
  • 举报
回复
楼主。。。在你的测试代码中只是注册了事件。但并没有激活事件..


//测试类
//ReceiveAlarm对象以参数形式传递给测试类,
public class Receiver
{
public Receiver(ReceiveAlarm mm)
{
//注册事件
mm.AlarmMsg += new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);

mm.AlarmMsg(this, e)
}

private void RecMsg(Object sender, ReceiveAlarm.AlarmMsgEventArgs e)
{
Console.WriteLine(" Receiving message:");
Console.WriteLine(" IP: {0}\n HostName: {1}\n Message: {2}\n Time {3}\n", e.ip, e.hostname, e.mess, e.time);
}

public void UnRegister(ReceiveAlarm mm)
{
mm.AlarmMsg -= new ReceiveAlarm.AlarmMsgEventHandler(RecMsg);
}
}



在红色处加上激活事件的代码。。
优途科技 2008-09-09
  • 打赏
  • 举报
回复
参考4楼代码。
mywisest 2008-09-08
  • 打赏
  • 举报
回复
是事件继承,参考以下代码:
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();
}
}
}
miyoo 2008-09-08
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 wisest 的回复:]
1.客户端事件方法应该是一个继承自 MarshalByRefObject 类型的实例方法。因为服务器是通过创建客户端的 MBR SAO 对象来实现回调的。
2. 缺省情况下,Delegate 无法被序列化,因此我们需要将服务器的 Formatter.TypeFilterLevel 设置为 Full。
[/Quote]
我的客户端ReceiveClient是继承自MarshalByRefObject,也能够接收到远程发来的消息,但是接收到消息后,我让他在触发ReceiveClient本地定义的事件AlarmMsg,就出现问题了!
mywisest 2008-09-08
  • 打赏
  • 举报
回复
1.客户端事件方法应该是一个继承自 MarshalByRefObject 类型的实例方法。因为服务器是通过创建客户端的 MBR SAO 对象来实现回调的。
2. 缺省情况下,Delegate 无法被序列化,因此我们需要将服务器的 Formatter.TypeFilterLevel 设置为 Full。
miyoo 2008-09-08
  • 打赏
  • 举报
回复
大侠帮忙

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧