About Remoting

xiaoxiao2021-03-05  30

I have seen many Remoting articles these few days. Understand a lot of technical details, but there is a lot of confusion. Simply put, Remoting is a distributed processing service. The server is first creating channels and automatically opens the listening channel. Pass the remote object according to the request sent by the client.

Therefore, writing the Remoting program, mainly divided into three parts: 1. Remote objects that are passed; 2. Server-side monitoring program; 3. Client request and handling object programs;

First, the remote object that is passed is in transotiet, which is limited to the remote object class. First, we must be clear that the so-called transmission is in the way, so the remote object class transmitted must inherit MarshalByrefObject. MarshalByrefObject is the base class of objects that communicate across the application domain boundaries by using the proxy switched message. Objects are not inherited from MarshalByrefObject to be encapsulated in implicit mode. When the remote application references a value-enclosed object, the copy of the object will be passed across the remote processing boundary. Because you want to communicate with a proxy method instead of a copy method, you need to inherit MarshallByrefObject. (MSDN)

public

Class

ServerObject: MarshalByrefObject

{Public Person getPersonInInfo (String name, string sex, int agent) {Person Person = new person (); person.name = name; person.sex = sex; person.age = age; return.age;}

This class only implements the easiest way to set up the basic information of a person and return a Person class object. It is worth noting that the Person class returned here. Since it is a reference and remote call. The Person transmitted here is completed in a passage. Therefore, a sequenceful problem must be involved.

Therefore, Remoting requires that the object class also calls or passes an object, such as classes, or structures, the class or structure must implement serialization Attribute. [Serializable].

[Serializable]

public

Class

Person

{Public person () {} private string name; private string sex; private int agent; public string name;} set {name = value;}} public string sex {get {return sex;} set {sex;} set {sex = Value;}} public int agent {get {return age;} set {agn = value;}}}

This server object is compiled into a DLL in the way, this work is completed.

So how is this object to be called by the client and server? This is what we have to do, add the compiled DLL to the server-side and client program, respectively. That is, this server object DLL is to copy two copies, put on the server side, put on the client. Why is this? After reading the code, you know the reason. As a result, there will be a problem. That is the security of the code. If the client must maintain the DLL of this object, the implementation of the object is almost transparent to the customer. In addition, this is not good for deployment. Two shared DLLs, if the object is passed, it will affect performance. For this issue, we can use the interface to solve. Obviously, the server side provides an interface and the implementation of the specific class, and the client only needs an interface (however, the client activation mode must have a class that implements the interface).

public

Interface

IServerObject

{Person getPersonInfo (String Name, String SEX, INT AGE);

public

Class

ServerObject: MarshalByrefObject, iServerObject

It is to be noted: 1, the name of the object set on both sides must be the same, strictly said that the name of the namespace must be the same. 2, this method is different depending on the activation method. If you are server-side activation (Singleton and Singcall), it is simple. The method as described above;

If the client is activated, it is best to use an abstract factory to provide a method of creating an instance. The following class chart describes the overall solution (MSDN).

Figure 1: Mixed structure

This must be added in the code and implementation of the abstract factory:

public

Interface

IServerObjFactory

{IServerObject CreateInstance ();

public

Class

ServerObject: MarshalByrefObject, iServerObject, iServerObjfactory

{Public iServerObject createInstance () {return new serverObject ();}}

However, due to the way client activation, it must call the class constructor to create an instance, so the interface seems impossible to implement the interface.

Description: About the object class inherits MarshalByrefObject, I have been testing, so that you can inherit indirectly. That is, we can inherit it by realizing the base class. The object that actually passes is derived from the base class.

The final code should be like this (the server side, if it is the client, only the interface is required. I added an abstract factory, so the object should be a client activation mode. If it is the server-side activation mode, the abstract factory should Interface and implementation method

Using

System;

Namespace

ServerRemoteObject

{[Serializable] public class Person {public Person () {} 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;}}} public interface IServerObject {Person GetPersonInfo (string name, string sex, int age);} public interface IServerObjFactory {IServerObject CreateInstance ();} public class ServerObject: MarshalByRefObject, IServerObject {public Person GetPersonInfo (string name, string sex, int age) {Person person = new Person (); person.Name = name; person.Sex = sex ...,;;;;;;; }} Public class ServerObjFactory: MarshalByRefObject, IServerObjFactory {public IServerObject CreateInstance () {return new ServerObject ();}}} to be added that the object passed here is clearly more than Socket, it may even pass DataSet object. In fact, we can understand it as WebService.

Second, the server side monitor program

Writing here, I would like to introduce three activation modes of the remote object. The activation mode is divided into two categories: server-side activation and client activation. The server-side activation is divided into: Singleton and SingleCall. 1. The server is activated and called a WellkNow mode. I don't want to tell theory, but just in accordance with my understanding. Simply put, Singleton activation means that all users have established an object instance, whether these users are on the same client or different clients. SINGLECALL is a remote object instance to each user of the client. As for the destruction of the object instance, it is automatically managed by GC. For example, if an accumulated method (i = 0; i) of the remote object is called by multiple clients (eg, two). If it is a Singleton mode, the first customer obtains a value of 1, and the second customer obtains a value of 2 because the object instance they get is the same. And SingleCall, two customers are 1. The reason is not selfless. 2, the client is activated. It is an instance to each client. Rough looks the same as SingleCall. It is actually different from. First, the target instance is not the same. The client activation method is to instantiate the client once issued a call; while SingleCall is created when the calling object method is called. Second, the WellkNow method is managed by GC, while the client can customize the life cycle, manage his destruction. Third, the WellkNow object is stateless, and the client activation object is stateful. Of course, it is not the same as that in use, the implementation is not the same.

Ok, now we start to create a server-side monitor program.

Remoting Transfer Remote Objects is essentially passed through Socket, so there must be a channel that passes an object. A channel must provide a port. In Remoting, the channel is provided by the iChannel interface. It has two types: TCPChannel and HttpChannel. TCP is transmitted in binary, and HTTP is transmitted in SOAP. The two channels have advantages, from performance, TCP is better. But HTTP can better pass the firewall. Therefore, the user can choose the way the channel is selected according to oneself. (This article uses TCPChannel, in fact, two can be mixed, now create TCPChannel, if the connection fails, created the httpchannel.) The class implemented class is the same name class, named space is under System.Runtime.Remoting.channel. The object can be transmitted through the channel, and multiple objects can be passed once. The transmission and selection of objects is implemented by RemotingConfiguratin's static method regiGuratin, REGISTERWELLKNOWNSERVICEPE () (for server activation mode) and registeractivedServiceType () (for client activation mode). code show as below:

Using

System;

Using

System.Runtime.Remoting;

Using

System.Runtime.Remoting.Channels;

Using

System.Runtime.Remoting.Channels.tcp;

Namespace

ServerRemoting

{/ ** ////

/// Class1 Summary Description. /// Class Server {/ ** //// /// The primary entry point of the application. /// [static "static void main (string [] args) {// creates channel, use 8080 port; TCPChannel Channel = New TcpChannel (8080); // Registration Channel; ChannelServices.RegisterChannel (ChannelS.RegisterChannel // passing objects; RemotingConfiguration.RegisterWellKnownServiceType (typeof (ServerRemoteObject.ServerObject), "ServiceMessage", WellKnownObjectMode.SingleCall); Console.WriteLine ( "Open the server listener"); Console.ReadLine ();}}} code is very simple. I am using the console to provide services. Here you focus on the parameters of the registerwellknownserviceType () method. The first parameter is to pass the type of object. The second parameter is the remote object service name you define, in fact it is part of the URI of the client. The third parameter is naturally a way to define activation. WellkNownObjectMode is an enumeration, two of SingleCall and Singleton.

If it is a client activation mode, it is slightly different:

RemotingConfiguration.ApplicationName

=

"

ServiceMessage

"

RemotingConfiguration.RegisterActiVatedServiceType

Typeof

(ServerRemoteObject.serverObject));

Some descriptions: 1, DLL references. To add the remote object DLL created by the first step; add a reference for system.Runtime.Remoting. 2. Several objects relating to a channel. In fact, it is not a complex, then use the regiSETERWELLLLKNOWNSERVICETYPE () method. As long as this object is in line with the requirements I told earlier, the reference is added. Of course, the client should also increase the corresponding code. 3. About the use of multiple channels. In Remoting, multiple channels can be used at the same time. But the channel name must be different. The default established TCPChannel name is TCP, the HTTPChannel name is HTTP. If you want to create a TCPChannel, you must define a name yourself. The Channel itself provides a ChannelName field, but this field is read-only. So the method is a bit change, use HashTable and IDictionary (to add the system.collection namespace):

IDictionary channelprops

=

New

Hashtable (); channelprops [

"

Name

"

]

=

"

MyTCP

"

; ChannelProps [

"

Priority

"

]

=

"

1

"

; ChannelProps [

"

Port

"

]

=

"

8081

"

TCPCHANNEL CHANNEL2

=

New

TCPChannel (ChannelProps,

New

SOAPCLIENTFORMATTERSINKPROVIDER (),

New

SOAPSERVERFORMATTERSINKPROVIDER ());

4, the service stop. For the use of channels, it is mainly used to deliver remote objects and turn on the channel to the channel. So we can close the listening to it. You can also log out of the channel directly. Turning off the statistening () method of monitoring the channel instance object. The logout channel is to use the ChannelServices.unregisterChannel () method. The closing monitors did not log out of the channel, just closed the listening to the client request. You can also reopen the listen through the startlistence () method. Once the channel is canceled, it is necessary to re-register the method of the registration channel as described above.

//

Get the currently registered channel;

IChannel [] Channels

=

ChannelServices.RegisteredChannels;

//

Turn off the channel specified as MyTCP;

Foreach

(IChannel Eachchannel

in

Channels

{If (eachChannel.ChannelName == "MyTcp") {TcpChannel tcpChannel = (TcpChannel) eachChannel; // close monitor; tcpChannel.StopListening (null); // cancellation channel; ChannelServices.UnregisterChannel (tcpChannel);}}

Third, client request and handling object programs

First see the code:

Using

System;

Using

System.Runtime.Remoting;

Using

System.Runtime.Remoting.Channels;

Using

System.Runtime.Remoting.Channels.tcp;

Namespace

ClientRemoting

{/ ** ////

/// Class1 Summary Description. /// Class Client {/ ** //// /// The primary entry point of the application. /// [STAThread] static void Main (string [] args) {TcpChannel channel = new TcpChannel (); ChannelServices.RegisterChannel (channel); ServerRemoteObject.IServerObject serverObj = (ServerRemoteObject.IServerObject) Activator.GetObject (typeof (ServerRemoteObject.IServerObject), "tcp: // localhost: 8080 / ServiceMessage"); Console.WriteLine ( "Invoke remoting object:"); ServerRemoteObject.Person person = serverObj.GetPersonInfo ( "wayfarer", "male", 28) Console.writeline ("Name: {0}, SEX: {1}, age: {2}", person.name, person.sex, person.Age); console.readline ();}}} code is very simple . Note that when the client is instantiated, it is the default constructor called, that is, the port number is not passed. In fact, this port number is not possible, but its designation is placed behind a part of the URI. This program focuses on this line of code:

ServerRemoteObject.iserverObject ServerObj

=

(ServerRemoteObject.iserverObject) Activator.GetObject (

Typeof

(ServerRemoteObject.IgRverObject),

"

TCP: // localhost: 8080 / serviceMessage

"

);

First activation with WellkNown mode, the client gets the object to use GetObject (). The first parameter is the type of remote object. As mentioned earlier, we only used the interface on the client, so the object returned should be the interface type. The second parameter is the server-side URI. If it is an HTTP channel, it is natural to use http: // localhost: 8080 / serviceMessage. Because I use a local machine, so this is localhost, you can use the specific server IP address instead of it. The port must be consistent with the port of the server. Later, it is a remote object service name defined by the server.

If the server is activated by the client, the method called is not the same. By the way, the above implementation also adds the DLL reference for the remote object. I have talked in front that this DLL named space name must be consistent with the server. Because our implementation is done on the same machine, everyone has to change the path to establish this object class library when establishing this client remote object.

Or return to the question just now, use the factory, then the code should be changed slightly, because the remote object is not directly instantiated, but is created through the factory. Obviously, we only need to change the above line of code:

RemotingConfiguration.registerActiVatedClientType

Typeof

(ServerRemoteObject.iserverObjFactory),

"

TCP: // localhost: 8080 / serviceMessage

"

ServerRemoteObject.iserverObjfactory Factory

=

New

ServerRemoteObject.serverObjFactory (); ServerRemoteObject.iserverObject Serverobj

=

Factory.createInstance ();

Even with an abstract factory, if it is the client activation mode, the remote object referenced by the client is still a specific implementation, not only by the implementation of the interface. From the above code, it knows that the method of obtaining an object instance is not to obtain an object instance with the activitor.getObject () method, but use the remoteConfiguration.RegisterActiVatedClientType () static method to register an object, and then call the class constructor.

How to be like a Wellknown mode, I have not thought of the implementation of the client only on the client.

Through the three steps above, Remoting procedures are completed. Pay attention to running, you need to run the server program and then run the client program.

Fourth, the improvement of the program

The program written above, the settings of the server URI, port, and activation mode are done with code. In fact, we can also set it with a configuration file. Doing this is good because this profile is an XML document. If you need to change the port or other, we don't need to modify the program and recompile, but only you need to change this configuration file.

1, the configuration file of the server side:

<

CONFIGURATION

>

<

System.Runtime.Remoting

>

<

Application Name

=

"

ServerRemoting

"

>

<

Service

>

<

Wellknown Mode

=

"

Singleton

"

Type

=

"

ServerRemoteObject.ServerObject

"

Objecturi

=

"

ServiceMessage

"

/>

Service

>

<

Channels

>

<

Channel

Ref

=

"

TCP

"

port

=

"

8080

"

/>

Channels

>

Application

>

System.Runtime.Remoting

>

CONFIGURATION

>

If it is a client activation mode, the WellkNown is changed to ActiVated and the Mode property is deleted.

Place this configuration file into the server program's application folder, named serverRemoting.config. Then, the previous server-side program can use this statement directly: RemotingConfiguration.configure ("ServerReming.config"); 2, client configuration file

<

CONFIGURATION

>

<

System.Runtime.Remoting

>

<

Application Name

=

"

ClientRemoting

"

>

<

Client URL

=

"

TCP: // localhost: 8080 / ServerRemoting

"

>

<

Wellknown Type

=

"

ServerRemoteObject.ServerObject

"

Objecturi

=

"

TCP: // localhost: 8080 / ServerRemting / ServiceMessage

"

/>

Client

>

<

Channels

>

<

Channel

Ref

=

"

TCP

"

port

=

"

8080

"

/>

Channels

>

Application

>

System.Runtime.Remoting

>

CONFIGURATION

>

If it is the client activation mode, the modification is the same. Call is also using the RemotingConfiguration.configure () method to call the configuration file stored on the client.

The configuration file can also be placed in Machine.config. If the client program is a web application, you can put it in Web.config.

转载请注明原文地址:https://www.9cbs.com/read-32410.html

New Post(0)