关于TCP通道的Remoting的基本使用方法:
一:首先导入命名空间System.Runtime.Remoting,然后
using System.Runtime.Remoting;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Tcp;
建一个简单的测试接口和它的实现类
namespace RemotingTest
{
public interface ISubject
{
string Say(string name);
}
public class Subject:MarshalByRefObject,ISubject
{
public string Say(string name)
{
return "Hi,"+name;
}
}
}
//因为Remoting传递对象是以引用的方式,所以所传递的远程对象类必须继承 MarshalByRefObject
建一个WinForm窗体作为服务器端,拖一个Button,在Button的点击事件里写上:
class ServerFrm
{
private void Server_Click(object sender,EventArgs e)
{
//监听端口8001
TcpChannel channel = new TcpChannel(8001);
channel.ChannelName="TestChannel";
//注册这个TCP协议通道
ChannelServices.RegisterChannel(channel,false);
//在TCP协议通道里将Subject注册为已知类型,传递一段叫“SayHi”的Uri
RemotingConfiguration.RegisterWellKnownServiceType(typeof(Subject),"SayHi",WellKnownObjectMode.SignleCall);
MessageBox.Show("服务器开始监听");
}
}
现在开始做客户端进行测试,先建一个接口ISubject
namespace RemotingTest
{
public interface ISubject
{
string Say(string name);
}
}
(注意,命名空间和接口名要和服务器端的完全相同)
同样建一个WinForm窗体,拖一个Button,在Button的点击事件里写上:
class ClientFrm
{
private void Client_Click(object sender,EventArgs e)
{
string name = "Bob";
//同样注册一个和服务器端通信的通道
ChannelServices.RegisterChannel(new TcpChannel());
//通过Activator.GetObject方法获得远程Remoting对象,这里的Url为本地8001端口的SayHi(Uri)
RemotingTest.ISubject sub = (RemotingTest.ISubject)Activator.GetObject(typeof(RemotingTest.ISubject),"tcp://localhost:8001/SayHi");
MessageBox.Show(sub.Say(name));
}
}
二:在Remoting中的远程对象中,如果还要调用或传递某个对象,例如实体类,或者结构,则该实体类或结构则必须实现可序列化Attribute[SerializableAttribute],比如:
[Serializable]
public class UserInfo
{
public UerInfo()
{
}
private string name;
private string sex;
private int age;
public string Name
{
get {return name;}
set {name = value;}
}
public string Sex
{
get {return sex;}
set {sex = value;}
}
public int Age
{
get {return age;}
set {age = value;}
}
}
将该远程对象以类库的方式编译成Dll,这个Dll将分别放在服务器端和客户端,以添加引用
三:注销通道
如果要关闭Remoting的服务,则需要注销通道,也可以关闭对通道的监听。在Remoting中当我们注册通道的时候,就自动开启了通道的监听。而如果关闭了对通道的监听,则该通道就无法接受客户端的请求,但通道仍然存在,如果你想再一次注册该通道,会抛出异常。
//获得当前已注册的通道
IChannel[] channels = ChannelServices.RegisteredChannels;
foreach(IChannel channel in channels)
{
//关闭名称为TestChannel的通道
if(channel.ChannelName == "TestChannel")
{
TcpChannel tcp = (TcpChannel)channel;
//关闭监听
tcp.StopListening(null);
//注销通道
ChannelServices.UnregisterChannel(tcp);
}
}
还有一种方法,相对上面这个较为复杂一点,但会大大简化服务器端和客户端的代码,因为要把需要的信息写在XML文件里。
按照上面的测试接口和类方法不变,用另一种方法实现Remoting的通信:
一:在服务器端建一个应用程序配置文件App.config,添加内容如下:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.runtime.remoting>
<application>
<channels>
<channel ref="tcp" port="8001">
</channel>
</channels>
<service>
<wellknown type="RemotingTest.Subject,Server" objectUri="Subject.rem" mode="SingleCall"/>
</service>
</application>
<customErrors mode="Off" />
</system.runtime.remoting>
</configuration>
其中channel节点指定了通信通道的类型和端口号,wellkonwn节点指定了type类型的格式:(命名空间.类,程序集名称)。
然后我们在服务器端的按钮点击事件里写上:
private void Server_Click(object sender,EventArgs e)
{
using(System.Runtime.Remoting.RemotingConfiguration.Configur(AppDomain.CurrentDomain.SetupInformation.ConfigurationFile,false))
{
MessageBox.Show("服务器开始监听");
}
}
就这样一句代码,无论在XML里增加多少个wellknown节点,都能一次性读取出来
我们在客户端也建一个App.config,添上这样几句:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Subject" value="tcp://localhost:8001/Subject.rem"/>
</appSettings>
</configuration>
然后在客户端的按钮点击事件里写上:
private void Client_Click(object sender,EventArg e)
{
RemotingTest.ISubject sub = (RemotingTest.ISubject)Activator.GetObject(typeof(RemotingTest.ISubject),System.Configuration.ConfigurationManager.AppSettings.Get("Subject"));
Message.show(sub.Say("Bob"));
}
OK,大功告成。
Http通道和Tcp通道的大体没什么区别,这里就不多做介绍了。本人也是Remoting的初学者,希望能和大家共同学习,共同进步!
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步