Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Microsoft Visual C++ .NET Professional Projects - Premier Press

.pdf
Скачиваний:
180
Добавлен:
24.05.2014
Размер:
26 Мб
Скачать
☆

This page intentionally left blank

 

 

Y

 

L

 

F

 

M

 

A

 

E

 

T

 

 

Team-Fly®

Chapter 30

Introducing

Remoting

The power of the .NET Framework lies within the CLR, which manages the execution of code at run time. Prior to .NET, each programming language had a different runtime, leading to the complexities in achieving interoperability

across applications, because each application executed in its own unique application domain. With the CLR, you have a common runtime, which ensures the interoperability between programming code written in different .NET languages. The introduction of CLR thus simplifies the task of providing cross-language interoperability and enhanced exception handling. CLR manages application execution and provides services to impart memory management, thread management, and so on. The interoperability between different programs has made the interaction of objects across different application domains much simpler. This interaction between objects across application domains is called remoting.

This chapter introduces you to the .NET remoting architecture and how it works. You’ll learn the intricacies of how remote objects are created, exposed, and passed at the server side. Then, you’ll learn how remote objects are called at the client side. You’ll also learn about the .NET communication channels that are required for communication between different application domains. To be precise, this chapter provides a detailed discussion on .NET remoting.

Introduction to .NET Remoting Architecture

Remoting refers to the ability of objects residing in different application domains, in different processes on the same computer, or on different computers on a network to communicate with each other. This, certainly, is a great feature based on the principal of interoperability across applications — the applications may even be running on different operating systems.

The actual implementation of remoting might seem like a complex process — this is not true anymore. The credit for simplifying the remoting architecture goes to the

.NET Framework, which provides many services, such as activation and lifetime control, and communication channels that are required by remote applications, to

INTRODUCING REMOTING

Chapter 30

873

 

 

 

 

interact with each other. You’ll lean about activation, lifetime, and communication channels later in this chapter.

Remoting basically involves interprocess communication. The following two sections deal with the basics of interprocess communication and present you with a bigger picture of .NET remoting. The smaller details about .NET remoting will be covered later in the chapter.

Interprocess Communication

Communication across different processes is called interprocess communication. This communication involves two processes, the server and the client process. The server process provides the functionality of a server object to its caller (client) outside the process. The client process makes calls to the server objects provided by the server process. Therefore, interprocess communication involves the following three entities:

Server. Provides the functionality of a server object outside the server process

Client. Makes calls to server objects

Transportation mechanism. Provides a mechanism to transport calls from server to client and vice versa

For a client to be able to call a server object, the client should have access to the address of the server object, which resides in the server process. However, the addresses are accessible only within the same process. On way to solve this problem could be to copy the server object to the client process. Then, the client can make calls to the methods of the server object. However, this solution is not appropriate when the objects are large. This would unnecessarily increase the bandwidth, take up client memory, and decrease the processing performance.

An intelligent solution to the problem of method calls of server objects is to pass the reference of the server object to the client. In such situations, the client uses this reference to call the methods of the server object. But, remember that the calls are not processed within the client process. All calls are processed within the remoting system, which acts as an intermediary between the server and the client process.

The remoting system collects the information about the call made by the client and passes it to the server process. At the server side, the call is interpreted and

874 Project 10 NETWORKING AND REMOTING IN VC++ .NET

passed to the appropriate server object. Finally, the result of the call is sent back to the client. This way, there is no overhead on the client memory. Moreover, the bandwidth is used economically — only to transport critical information, such as the call, call arguments, method return values, or any exceptions.

The .NET Remoting Framework – A Bigger Picture

The entire remoting framework relies on passing the reference of server objects to the client process. In the previous section, you saw the way the client and server processes communicate with each other using the remoting system. The .NET Framework has simplified the remoting architecture to such a level that the entire system works on its own without the client realizing that a great task, such as accessing the functionality of a server object of a process on some remote computer, is being performed. For this entire system to work, the only thing that is required is the proper configuration of the client and server. Configuration is covered later in this chapter.

If you’ve configured both the client and the server properly, the client creates a new instance of the server class so that it can access the functionality provided by the server object. The remoting system in turn creates a proxy object (covered later in this chapter) representing the server class and passes the reference of this proxy object to the client. Then, whenever the client makes a call for a method of the server object, the client remoting system collects the information about the call and sends it to the server over a communication channel (covered later in this chapter). At the server side, after the processing, the results are sent from the server channel to the client channel. Finally, the client remoting system sends the results to the client through the proxy object.

Figure 30-1 illustrates the entire .NET remoting architecture.

Figure 30-1 gives you an overview of how remoting works. The following sections cover each and every aspect of remoting in further detail.

Remote Objects – Server Side

A remote object is an object that resides outside an application domain. For a client process to access a server object (which is a remote object), the reference of the server object must be passed to the client.

INTRODUCING REMOTING

Chapter 30

875

 

 

 

 

FIGURE 30-1 The .NET Remoting architecture

When an object is passed from one application domain to another, the remoting system first serializes the object and then transports it to the destination application domain. At the destination application domain, the object is then re-created. Therefore, the objects that cannot be serialized cannot be transported to another application domain and thus cannot act as remote objects. A remote object, therefore, must fulfill one of the following conditions:

A remote object must be marked with the [serializable] attribute.

A remote object must implement the ISerializable interface.

NOTE

A local object can be changed to a remote object by inheriting it from MarshalByRefObject.

Hosting Remote Objects

Now you are aware that the first condition for an object to be a remote object is that the object should be serializable. Such objects can be hosted in any one of the following ways:

876Project 10 NETWORKING AND REMOTING IN VC++ .NET

Managed executable. A remote object can be hosted as a .NET EXE or a managed service.

IIS. A remote object is exposed as a Web service by hosting it in Internet Information Server (IIS). To host a remote object in IIS, you should create a virtual root and copy the configuration file, Remoting.cfg, to this directory. Then, you should place the EXE or DLL of the remote object in the bin directory under the directory that the IIS root points to.

Remember that the name of the IIS root should be the same as the name of the application specified in the configuration file. Configuration files are covered in detail later in this chapter.

.NET component service. A remote object can be hosted as a .NET component service. Such remote objects take advantage of the Component Object Model (COM) features, such as transactions and Just In Time ( JIT) compilation.

Configuring Remote Objects

In the preceding section, you learned the different ways in which a remote object can be hosted so that it can be exposed to client application domains. In this section, you’ll learn the different ways in which a server object can be configured to act as a .NET remote object. The way a remote object is configured depends on the application requirement.

There are three different ways in which you can configure a server object to act as a remote object:

Single call objects. Such objects process only single requests coming in and cannot store state information across method calls. Single call objects are useful in situations in which the object is required to perform only a limited amount of work and maintaining state information is not necessary.

Singleton objects. Such objects can process requests coming in from multiple clients. Therefore, these objects can share data by maintaining state information. Singleton objects are useful in situations in which the data needs to be explicitly shared between clients.

Client activated objects (CAOs). Such objects are activated on the client request. When a client activates a server object (by using the new operator), the activation request message is sent to the destination remote application. The server then creates an instance of the requested

INTRODUCING REMOTING

Chapter 30

877

 

 

 

 

class and returns an ObjRef object back to the client. Using this ObjRef, a proxy object is created at the client side. Therefore, for every activation of the new operator, a proxy to a new instance of the server type is created. This manner of activation of server objects is similar to the classic COM method of activation.

Passing Remote Objects

A server application can pass a remote object to a client application in any one of the following manners:

As parameters to method calls

As return values of method calls

As values resulting from a property or field access of a .NET component

The following is the code for a remote object implemented as a Managed C++ class library:

namespace Quotes

{

public __gc class CQuote:public MarshalByRefObject

{

public:

String* getQuoteOfTheDay()

{

return “All quotable quotes have already been quoted”;

}

// TODO: Add your methods for this class here. };

}

This remote object needs to be housed in a server application. Create a Managed C++ application and update the _tmain method as follows:

int _tmain(void)

{

TcpChannel* pChannel2 = new TcpChannel(8085);

ChannelServices::RegisterChannel(pChannel2);

Type* pType = __typeof(nsRemoting::CQuote);

RemotingConfiguration::RegisterWellKnownServiceType(pType, “Quote”,

878 Project 10 NETWORKING AND REMOTING IN VC++ .NET

WellKnownObjectMode::SingleCall);

Console::WriteLine(“Please hit <ENTER> to exit...”);

Console::ReadLine();

return 0;

}

You can access the remote object (residing in the server application) from a client application by using the following code:

m_pQuote = (CQuote*) Activator::GetObject(__typeof(nsRemoting::CQuote),

“tcp://localhost:8085/Quote”);

A remote object can be marshaled by value (MBV) or marshaled by reference (MBR). I’ll discuss each of the methods in detail.

Marshal by Value

The remote objects that are not derived from MarshalByRefObject are marshal by value. When such objects are passed from a server application to a client application, a complete copy of the object is made. Now, before I proceed further, recall that in the beginning of this chapter, I stated that passing remote objects by value is not an intelligent solution when the objects are large. However, when objects to be passed are small and performance is the main concern, passing objects by value comes in handy. This method reduces round trips across boundaries, which includes boundaries of networks, processes, and application domains.

This method does not involve creating proxy objects. In fact, a copy of the remote object is automatically made when the object is called across boundaries; the CLR automatically takes care of the following scenarios:

Remote objects are passed between application domains in the same physical process

Remote objects are passed between application domains in different physical processes on the same computer

Remote objects are passed between application domains in different physical processes on different computers

The following code is for creating a remote object using the Serializable attribute:

using namespace System;

INTRODUCING REMOTING

Chapter 30

879

 

 

 

 

namespace r3

{

[Serializable]

public __gc class Class1

{

public:

String* getQuoteOfTheDay()

{

return “All quotable quotes have already been quoted”;

}

};

}

Marshal by Reference

The remote objects that are derived from MarshalByRefObject are marshal by reference. When such objects are passed from a server application to a client application, the object reference (ObjRef object) is passed to represent a proxy object in the client application domain. The ObjRef object contains the metadata information, such as the information about the type of the object being marshaled and a unique URI for the object. The following code is for creating a remote object that will use marshal by reference:

using namespace System;

namespace r3

{

public __gc class Class1:public MarshalByRefObject

{

public:

String* getQuoteOfTheDay()

{

return “All quotable quotes have already been quoted”;

}

};

}