Change
在无知的时候,我们常常会笑他人的肤浅。但终会明白,肤浅的是自己。

导航

统计
  • 随笔 - 6
  • 文章 - 0
  • 评论 - 129
  • 引用 - 0
公告
 

关于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的初学者,希望能和大家共同学习,共同进步!

posted on 2009-03-09 17:45 Funeral 阅读(...) 评论(...) 编辑 收藏