.Net 3.5 Remoting编程入门三
VS2008 .Net 3.5 Remoting编程入门三
信道
什么是信道?信道有哪些类型呢?
信道顾名思意就是通信的通道。就想那些宣传标语说的,“要想富,先修路!”。同理,要学习Remoting,当然要学习信道了。
.NET Framework 远程处理基础结构提供下列信道实现:
IpcChannel
TcpChannel
HttpChannel
IpcChannel
IpcChannel 类使用命名管道为同一台计算机上的多进程应用程序提供高速进程间通信。IpcChannel 执行下列功能:
使用命名管道在发送方和接收方之间通信。
支持以二进制格式和行业标准 SOAP 序列化格式编码负载。
生成并使用对象引用的 ChannelDataStore。
支持模拟和委托。
支持在命名管道上利用访问控制列表 (ACL) 来提供高级访问控制。
当一个应用程序必须与同一台计算机上其他进程中运行的另一个应用程序通信时,就应当使用 IpcChannel。由于 IpcChannel 使用命名管道,因此应用程序通常能够获得最高的通信性能,并可以使用模拟和委托来控制对远程对象的访问。对于三层应用程序而言,其第二层和第三层之间的通信必须能够在负载下运行良好。此时,这一功能便尤其有用。
TcpChannel
TcpChannel 类使用二进制格式化程序将所有消息序列化为二进制流,并使用 TCP 协议将该流传输至目标统一资源标识符 (URI)。TcpChannel 执行下列功能。
使用 TCP 套接字在发送方和接收方之间通信。
支持以二进制格式和行业标准 SOAP 序列化格式编码负载。
生成并使用对象引用的 ChannelDataStore。
支持模拟和委托。
支持 SSPI 加密。
TcpChannel 会根据该时刻向另一台服务器发送请求的线程数打开并缓存相应数目的连接。当套接字连接的非活动时间超过 15-20 秒后,客户端将关闭这些连接。
在生成大量使用 .NET Framework 远程处理的应用程序时,很容易错误地使用 HttpChannel 连接至用 TcpChannel 进行侦听的服务器应用程序域。如果建立了这种连接,客户端将收到以下异常:“基础连接已经关闭: 接收时发生错误”。如果您的客户端收到此异常,则应当检查客户端和服务器,以确定是否存在信道不匹配的问题。
HttpChannel
HttpChannel 类使用 SOAP 协议在远程对象之间传输消息。所有消息都通过 SoapFormatter 传递,此格式化程序会将消息转换为 XML 并进行序列化,同时向数据流中添加所需的 SOAP 标头。如果还指定了二进制格式化程序,则会创建二进制数据流。随后,将使用 HTTP 协议将数据流传输至目标 URI。HttpChannel 符合 SOAP 1.1 标准,它执行下列功能:
通过将 HTTP 协议用作传输在发送方和接收方之间通信。
支持以 SOAP(一种 XML 编码标准)和二进制格式编码负载。
将接收方设置为通过 ASP.NET 和 TCP 套接字接收 HTTP 请求并发送 HTTP 响应。
生成并使用对象引用的 ChannelDataStore。
支持模拟和委托。
支持 SSPI 加密。
HttpChannel 一次只向给定服务器打开指定数目的连接。默认值为 2,但您可以使用应用程序配置文件中的 clientConnectionLimit 属性更改该默认值。
在生成大量使用 .NET Framework 远程处理的应用程序时,很容易错误地使用 HttpChannel 连接至用 TcpChannel 进行侦听的服务器应用程序域。如果建立了这种连接,客户端将收到以下异常:“基础连接已经关闭: 接收时发生错误”。如果您的客户端收到此异常,则应当检查客户端和服务器,以确定是否存在信道不匹配的问题。
以上摘自MSDN,已经说的很明白了。
每种类型的channel都有对应的clientchannel和serverchannel两中形式。在一般情况下,我们直接使用一种类型的channel,负责接受和发送。
下面看看代码怎么写的。
远程对象类,RemotingClass.cs和以前的一样,不要改变。
using System;
namespace RemotingClass
{
public class Message : MarshalByRefObject
{
public Guid MessageId { get; set; } //Guid,用于保存Message的ID
public Message()
{
this.MessageId = Guid.NewGuid();//当对象被实例同时产生一个ID
}
public delegate void MessageHandler(string msg);
public static event MessageHandler OnSendMessage;
public void SendMessage(string msg)
{
if (OnSendMessage != null)
OnSendMessage("Message的ID是:" + this.MessageId + msg);
}
}
}
服务端代码:(注意看注释的地方)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;//使用IpcChannel
//using System.Runtime.Remoting.Channels.Http;//使用HttpChannel
//using System.Runtime.Remoting.Channels.Tcp;//使用TcpChannel
namespace Server
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Host Started!");
//HttpChannel channel = new HttpChannel(20001);//创建HttpChannel通道
//TcpChannel channel = new TcpChannel(20001);//创建TcpChannel通道
IpcChannel channel = new IpcChannel("localhost:20001");//创建IpcChannel通道,和http、tcp有点不一样,其他的地方基本一样。
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownServiceType(typeof(RemotingClass.Message), "Message.rem", WellKnownObjectMode.SingleCall); //这里使用SingleCall即可
RemotingClass.Message.OnSendMessage += new RemotingClass.Message.MessageHandler(Message_OnSendMessage);
Console.Read();
}
public static void Message_OnSendMessage(string msg)
{
Console.WriteLine(msg);
}
}
}
客户端代码:(注意看注释的方法)
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
//using System.Runtime.Remoting.Channels.Http;//使用HttpChannel
//using System.Runtime.Remoting.Channels.Tcp;//使用TcpChannel
namespace Client
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Client Started!");
// HttpChannel channel = new HttpChannel();//创建HttpChannel通道
// TcpChannel channel = new TcptChannel();//创建TcpChannel通道
IpcChannel channel = new IpcChannel();//创建IpcChannel通道
ChannelServices.RegisterChannel(channel, false);
RemotingConfiguration.RegisterWellKnownClientType(typeof(RemotingClass.Message), "ipc://localhost:20001/Message.rem");
//注意此处的协议,不同的通道使用不同的协议。如果是httpchannel,则使用http,如果是tcpchannel,则请使用tcp
RemotingClass.Message msg = new RemotingClass.Message();
while (true)
{
msg.SendMessage(" 现在是:" + System.DateTime.Now.ToString());
System.Threading.Thread.Sleep(2000);
}
//Console.ReadLine();
}
}
}