C#netremoting sample code sharing for two-way communication

Source: Internet
Author: User
This article mainly describes the C # netremoting implementation of two-way communication,. Net Remoting is provided by the client through Remoting, access the channel to obtain the server side http://www.php.cn/wiki/60.html "Target=" _ Blank "> object, and then through proxy resolution to the client object to achieve communication

Idle to have no matter want to play two-way communication, to achieve similar QQ message of the function of each other. So start learning. Net Remoting.

. Net Remoting is provided by the client through Remoting, access the channel to obtain the service-side object, and then through the proxy resolution to the client object to achieve communication. This means that the object is created by the server.

First on the code

First, the ICommand library.

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>///Add operation///</summary>//<param name= "x1" > Parameters 1</param>//<param N    Ame= "x2" > Parameters 2</param>///<returns></returns> string SUM (int x1, int x2);    <summary>///Get a list of server events///</summary> delegate[] getservereventlist (); <summary>/////</summary>//<param name= "info" ></param>//<param NA    Me= "ToName" ></param> void Toserver (object info, string toname); <summary>//Reception information//</summary>/<param name= "info" ></param>//<param NA Me= "ToName" ></param> void Toclient (object info, String ToName);    void Tologin (string name);  void Toexit (string name); }///<summary>//Client Send message///</summary>//<param name= "info" > Information </param>//<param NA Me= "ToName" > Send to WHO, "" means everyone, null means no receiving server itself received, other means specify someone </param> public delegate void Sendhandler (object info,  String toname); <summary>///client receive messages///</summary>//<param name= "info" > Information </param>//<param name= "ToName" > Send to WHO, "" means everyone, null means no receiving server itself received, other means specify someone </param> public delegate void Receivehandler (object info,  String toname); <summary>///user Information events///</summary>//<param name= "name" > User name </param> public delegate Voi D Userchangedhandler (string name);}
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>//    Reception information//    </summary>/    <param name= "info" ></param>    // <param name= "ToName" ></param> public    void Toclient (object info, string toname)    {      if (_ Receive! = NULL)        _receive (info, toname);    }    Infinite life cycle public     override Object InitializeLifetimeService ()    {      return null;    }    Private Receivehandler _receive;  } }

The first class is to define some interfaces, and some delegates, with no substantive stuff.

The second class is the event and method that defines the toclient in the previous interface class, as described in the action.

Then there is the substantive data class that integrates the ICommand interface.

Using system;using system.collections.generic;using system.linq;using system.text;using ICommand;namespace netremoting{public class Remotingobject:marshalbyrefobject, Iremotingobject {//<summary>///Send Event/      </summary> public Event Sendhandler Clienttoserver {add {_send + = value;}    Remove {_send-= value;}    }///<summary>///Receive Message events///</summary> public event Receivehandler Servertoclient;  <summary>///Send Event///</summary> public event Userchangedhandler Login {add {_login + = Value    } remove {_login-= value;}  }///<summary>///Send Event///</summary> public event Userchangedhandler Exit {add {_exit + = value;    } remove {_exit-= value;} }//<summary>///Add operation///</summary>//<param name= "x1" > Parameters 1</param>//&LT;PA Ram Name= "x2" > Parameters 2</param>//<returns></retuRns> public string SUM (int x1, int x2) {return x1 + "+" + x2 + "=" + (x1 + x2); }///<summary>///The event method that binds the server to send messages to the client//////<param Name= "Receive" > Receive event </par Am> public delegate[] Getservereventlist () {return this.    Servertoclient.getinvocationlist (); }///<summary>/////</summary>//<param name= "info" ></param>///<par        Am Name= "toname" ></param> public void Toserver (object info, string toname) {if (_send! = null)    _send (info, toname); }///<summary>/////</summary>//<param name= "info" ></param>///<par        Am Name= "toname" ></param> public void Toclient (object info, string toname) {if (_receive! = null)    _receive (info, toname); }///<summary>//Login///</summary>/<param name= "name" > User name </param> public voi D toLogin (string name) {if (!_namehash.contains (name)) {_namehash.add (name);      if (_login! = null) _login (name);    } else {throw new Exception ("User already Exists");} }///<summary>///<param Name= "name" > User name </param> public voi        D 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> (); }}

This class integrates the MarshalByRefObject

Because the object passed by remoting is referenced, the remote object class passed must inherit MarshalByRefObject. MSDN's description of MarshalByRefObject is that MarshalByRefObject is the base class for objects that communicate across application domain boundaries by using proxies to exchange messages. Objects that are not inherited from MarshalByRefObject are implicitly marshaled by value. When a remote application references an object that is marshaled by value, a copy of the object is passed across the remoting boundary. Because you want to communicate using a proxy method instead of a copy method, you need to inherit marshallbyrefobject.

The class primarily defines some methods for client-side triggering events, Toserver,toclient,tologin,toexit and events, client-to-server events, and server-to-client events.

_namehash just records which users are logged in.

The next is the client and the service side.

First service side:

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>//Registration Channel///</summary>//<param name= "sender" ></param>//<p Aram Name= "E" ></param> private void Server_load (object sender, EventArgs e) {Channelservices.register      Channel (_channel, false); RemotingConfiguration.RegisterWellKnownServiceType (typeof (Remotingobject), "Summessage", Wellknownobjectmode.singleton); A scheme/* Converts the given system.marshalbyrefobject to system.ru with the specified URINtime.       An instance of the Remoting.objref class. OBJREF: Stores all the information required by the build agent to communicate with the remote object. */ObjRef ObjRef = Remotingservices.marshal (_remotingobject, "summessage");//b scheme _remotingobject.clienttoserver + = (info, toname) = {Rxtinfo.invoke ((MethodInvoker) (() = {Rxtinfo.appendtext (info). ToString () + "\ r \ n");        }));      Sendtoclient (info, toname);      }; _remotingobject.login + = (name) = {Rxtinfo.invoke ((MethodInvoker) (() = {Rxtinfo.appendtext (name +) Login "+" \ r \ n ");      }));      }; _remotingobject.exit + = (name) = {Rxtinfo.invoke ((MethodInvoker) (() = {Rxtinfo.appendtext (name + Out "+" \ r \ n ");      }));    }; }//<summary>//Cancellation channel///</summary>//<param name= "sender" ></param>//<p Aram Name= "E" ></param> private void Server_formclosing (object sender, FormClosingEventArgs e) {if (_c Hannel! = null) {_channel.        Stoplistening (NULL); ChannelServices.Unregisterchannel (_channel); }}///<summary>////</summary>//<param name= "sender" ></param>// <param name= "E" ></param> private void Btnsend_click (object sender, EventArgs e) {sendtoclient (txts End.    Text, txtName.Text); }///<summary>///Send message to client///</summary>//<param name= "info" ></param>//&lt  ;p Aram Name= "ToName" ></param> private void Sendtoclient (object info, string toname) {//foreach (Var V In _remotingobject.getservereventlist ())//{//try//{//Receivehandler receive = (Receivehan      Dler) v; Receive.      BeginInvoke (info, toname, NULL, NULL);    }//Catch//{}//} _remotingobject.toclient (Txtsend.text, txtName.Text); }///<summary>//Initialize///</summary> private void Initialize () {//Set deserialization level of Binary Serverformattersinkprovider sErverprovider = new BinaryServerFormatterSinkProvider ();      Binaryclientformattersinkprovider Clientprovider = new Binaryclientformattersinkprovider (); Serverprovider.typefilterlevel = typefilterlevel.full;//supports all types of deserialization, high level IDictionary idic = new dictionary<string      , string> ();      idic["name"] = "serverhttp";      idic["port"] = "8022";      _channel = new HttpChannel (Idic, Clientprovider, Serverprovider);    _remotingobject = new Remotingobject ();    } HttpChannel _channel;  Private Remotingobject _remotingobject; }}

Then the client:

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 ICommand;using system.runtime.serialization.formatters;using system.collections;namespace netremotingclient{public partial class    Client:form {public Client () {InitializeComponent (); }///<summary>//Registration Channel///</summary>//<param name= "sender" ></param>//<p Aram Name= "E" ></param> private void Client_load (object sender, EventArgs e) {try {//Set reverse order        Column level BinaryServerFormatterSinkProvider Serverprovider = new BinaryServerFormatterSinkProvider ();        Binaryclientformattersinkprovider Clientprovider = new Binaryclientformattersinkprovider (); Serverprovider.typefilterlevel = Typefilterlevel.full;//supports all types of deserialization, high-level//Channel port IDictionary idic = new dictionary<string, string> ();        idic["name"] = "clienthttp";        idic["port"] = "0";        HttpChannel channel = new HttpChannel (Idic, Clientprovider, Serverprovider);        ChannelServices.RegisterChannel (channel, false); _remotingobject = (iremotingobject) Activator.GetObject (typeof (Iremotingobject), "Http://localhost:8022/SumMessage        ");        _remotingobject.servertoclient + = (info, toname) = {Rtxmessage.appendtext (info + "\ r \ n");};        Swapobject swap = new Swapobject (); _remotingobject.servertoclient + = swap.        Toclient; Swap.          Swapservertoclient + = (info, toname) = {Rtxmessage.invoke (MethodInvoker) (() = {        if (ToName = = Txtlogin.text | | toname = = ") Rtxmessage.appendtext (info +" \ r \ n ");        }));      }; } catch (Exception ex) {MessageBox.Show (ex. Message); }}///<summary>//Login   </summary>//<param name= "sender" ></param>//<param name= "E" ></param> PR ivate void Btnlogin_click (object sender, EventArgs e) {try {if (Txtlogin.text = = "") throw        New Exception ("User name must not be null");      _remotingobject.tologin (Txtlogin.text); } catch (Exception ex) {MessageBox.Show (ex.      Message); }}///<summary>///<param name= "sender" ></param>///&L       T;param name= "E" ></param> private void Client_formclosing (object sender, FormClosingEventArgs e) {try      {_remotingobject.toexit (Txtlogin.text); } catch {}}//<summary>////</summary>//<param name= "Sender" ><      /param>//<param name= "E" ></param> private void Btnsend_click (object sender, EventArgs e) { Rtxmessage.appendtext (_remotingobject.sum (2, 4) + "\r\n ");    _remotingobject.toserver (Txtsend.text, txtName.Text);  } private Iremotingobject _remotingobject; }}

Service-Side implementation steps:

1. Registration Channel

To communicate across an application domain, you must implement a channel. As mentioned earlier, remoting provides a ichannel interface that contains TcpChannel and HttpChannel two types of channels respectively. These two types are implemented in exactly the same way except for the performance and serialization data formats, so let's take TcpChannel as an example.

To register TcpChannel, first add the reference "System.Runtime.Remoting" to the project, and then the using namespace: SYSTEM.RUNTIME.REMOTING.CHANNEL.TCP. The code is as follows:

TcpChannel channel = new TcpChannel (8022); ChannelServices.RegisterChannel (channel);

When instantiating a channel object, pass the port number as a parameter. Then call the static method RegisterChannel () to register the channel object.

2. Registering a remote object

After the channel is registered, the object must be registered in the channel to be able to activate the remote object. Depending on the activation mode, the methods for registering objects are different.

(1) Singleton mode

For WellKnown objects, the static method RemotingConfiguration.RegisterWellKnownServiceType () can be implemented:

RemotingConfiguration.RegisterWellKnownServiceType (        typeof (Serverremoteobject.serverobject),        " Servicemessage ", Wellknownobjectmode.singleton);

(2) SingleCall mode

The method of registering an object is basically the same as the singleton mode, and you only need to change the enumeration parameter WellKnownObjectMode to SingleCall.


RemotingConfiguration.RegisterWellKnownServiceType (        typeof (Serverremoteobject.serverobject),        " Servicemessage ", WellKnownObjectMode.SingleCall);

Client implementation steps:

1. Registration Channel:

TcpChannel channel = new TcpChannel (); ChannelServices.RegisterChannel (channel);

Note When a client instantiates a channel, it is the default constructor that is called, that is, the port number is not passed. In fact, this port number is integral, except that its designation is placed behind it as part of the URI.

2. Get the remote object .

As with the server side, different activation modes determine how the client will be implemented differently. However, this difference is only the difference between the wellknown activation mode and the client activation mode, and the client implementation is identical for Singleton and SingleCall modes.

(1) WellKnown activation mode

To obtain a well-known remote object on the server side, you can obtain it through the GetObject () method of the Activator process:

Serverremoteobject.serverobject ServerObj = (serverremoteobject.serverobject) activator.getobject (       typeof ( Serverremoteobject.serverobject), "Tcp://localhost:8080/servicemessage");

First activated in wellknown mode, the client obtains the object by using GetObject (). Where the first parameter is the type of the remote object. The second parameter is a server-side URI. If it is an HTTP channel, it is natural to use Http://localhost:8022/ServiceMessage. Because I am using a local machine, so here is localhost, you can use the specific server IP address to replace it. The port must be the same as the server-side port. The following is the server-defined remote object service name, which is the contents of the ApplicationName property.

Sets the deserialization level         binaryserverformattersinkprovider serverprovider = new BinaryServerFormatterSinkProvider ();        Binaryclientformattersinkprovider Clientprovider = new Binaryclientformattersinkprovider ();        Serverprovider.typefilterlevel = typefilterlevel.full;//support for all types of deserialization, high level         /channel port         IDictionary idic = new Dictionary<string, string> ();        idic["name"] = "clienthttp";        idic["port"] = "0";        HttpChannel channel = new HttpChannel (Idic, Clientprovider, Serverprovider);

You can see from the above code that the registration method has changed because the client registers the server event with an error "do not allow type deserialization".

There is also a need to note that:

ObjRef ObjRef = Remotingservices.marshal (_remotingobject, "summessage");// RemotingConfiguration.RegisterWellKnownServiceType (typeof (Remotingobject), "Summessage", Wellknownobjectmode.singleton);//The call system is created automatically, resulting in the instantiation of the _remotingobject object, so that late-bound events cannot be manipulated, of course, can also be directly static event binding, This way, you don't need to instantiate the object manually.

This method is used to manually create the instantiation of the _remotingobject object.

And then we talked about a swapobject class, the role of this class is event exchange.

_remotingobject.servertoclient + = Method ();//So because this method is client-side, the server cannot be called, so an intermediate conversion of swapobject swap = new Swapobject () is required;// First create a Swap object _remotingobject.servertoclient + = swap. Toclient; Then the server event sends a message to swap, and then the swap is sent to the client via the event, swap is created by the client so it can be sent, and swap is the service-side class, so the server can also recognize that swap plays a role in the middle transition swap. Swapservertoclient + = Method ();
Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.