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

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

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

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

Testing

The development team has to test the application before passing it on to the departments for a beta test. Therefore, it needs to test both the server and the client components and verify the functioning of the complete application.

Before getting started with the coding of the application, you need to understand some of the basic concepts involved in remoting. So, I will first discuss those con-

cepts, and then explain the coding.

Y

.NET Remoting

 

L

.NET Remoting allows you to create powerful and high-performance distributed

applications. In Chapter 23, you haveFalready seen how to create distributed appli-

cations by using Web services. Web services allow you to create applications where

the different components are looselyMcoupled. Hence, a Web service provides a

flexible architecture at theAcost of performance. On the other hand, the .NET

E

 

T

 

remote objects allow you to access resources across the network without the overhead posed by SOAP-based Web services.

The .NET Remoting architecture is used whenever a method call occurs across machine boundaries. It is also invoked when the method call occurs across process and AppDomain boundaries. An AppDomain in a .NET process has a similar significance and role as a process in the operating system.

An AppDomain is a process within a process, and a process can contain multiple AppDomains. Every .NET object is created within an AppDomain. An AppDomain can contain not only individual objects, but also entire .NET applications. You can even have more than one application running under a single AppDomain. This promotes better use of resources.

An object in an AppDomain is not directly accessible by an object in another AppDomain. If an object of a class, say Class1, has to be accessible in another AppDomain, then Class1 needs to be remotable either by value or by reference. A class can be made remotable by using the [Serializable] attribute. Serialization results in an exact copy of the Class1 object being created in the calling AppDomain. However, any changes to the Class1 object in the calling AppDomain will not affect the original object.

Making the same class derive from the System::MarshalByRefObject class will make it remotable by reference. When an object is made remotable by reference,

Team-Fly®

IMPLEMENTING REMOTING

Chapter 31

891

 

 

 

 

the calling AppDomain gets access to a proxy of the object, and any changes in the calling AppDomain are reflected in the object.

Creating the Remote Object Application

To create the remote object, run Visual Studio.NET and create a new Managed C++ class library project. Assign the name of the project as RemoteObject. The IDE will create the following files:

RemoteObject.h

RemoteObject.cpp

AssemblyInfo.cpp

Stdafx.h

Stdafx.cpp

The file RemoteObject.h contains an empty implementation of a class Class1 under the namespace RemoteObject. Change the name of the class and the namespace as indicated in the following code snippet:

namespace nsRemoting

{

public __gc class CQuizServer : public MarshalByRefObject

{

public:

};

}

Let me explain the preceding code snippet. I’ve also highlighted the line in the code that I’m dealing with in this explanation.

The MarshalByRefObject class is the base class for objects that need to support communication across processes, application domains, and machine boundaries. Objects that do not inherit are implicitly considered to be marshaled by value objects. MarshalByRef objects are accessed within the boundaries of the local AppDomain. The first time a client application connects to a server object in a different AppDomain, a proxy is passed to the client application. The subsequent calls are marshaled by the proxy to the remote object.

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

The namespace has been modified to nsRemoting. The class name has been changed to CQuizServer and it derives from the MarshalByRefObject class. Refer to the discussion of AppDomains and Remoting (in the “.NET Remoting” section earlier in this chapter) to understand why the CQuizServer class needs to

derive from MarshalByRefObject.

Next, you need to add some methods to the class. The class needs to have methods for providing the following functionality:

Return a question whenever a client application invokes the method

Return the various options to the client

Return the correct answers

Greet the user

Ideally, all this data should be in a database. However, currently the team is creating a beta application. It will distribute it to the departments and, based on the suggestions and feedback from the users, add more functionality and create a fullfledged application. Then, the team will add a database to store the related data.

Take a look at some of the important methods in the remote object before you code the same:

String* GetNextQuestion(int m_nNum). Takes a question number as input and returns the corresponding question text.

String* GetOptions(int nQNum, int nOption). Accepts a question number and an option number, and returns the corresponding option text.

int GetAnswer(int nNum). Returns the correct answer for the question number passed as input.

Here is the complete code for the class. I have highlighted the lines of code that you need to add in Bold.

namespace nsRemoting

{

public __gc class CQuizServer : public MarshalByRefObject

{

public:

CQuizServer()

{

}

IMPLEMENTING REMOTING

Chapter 31

893

 

 

 

 

~CQuizServer()

{

}

//The method to greet the users

String* DoWelcome(String* strName)

{

String* strTemp; strTemp = strName;

strName = String::Concat(S”WELCOME “, strTemp); return strName;

}

//Sends the Questions to the client

String* GetNextQuestion(int m_nNum)

{

String* pStrQ; switch(m_nNum)

{

case 1:

pStrQ = “How many Continents are there in the world?”; break;

case 2:

pStrQ = “How many states are there in United States of America?”;

break;

case 3:

pStrQ = “Which is the largest country in the world?”; break;

case 4:

pStrQ = “In which state is the Golden Gate Bridge situated?”;

break;

case 5:

pStrQ = “Which is the largest planet of the solar system?”; break;

case 6:

pStrQ = “Which planet is closest to the sun?”; break;

case 7:

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

pStrQ = “Argentina is in which continent?”; break;

case 8:

pStrQ = “What is the capital of India?”; break;

case 9:

pStrQ = “What is the currency of Japan?”; break;

case 10:

pStrQ = “Where is the Eiffel Tower?”;

break;

default:

pStrQ = “?????”; break;

}

return pStrQ;

}

//Accepts the question number, option number and returns the option text

String* GetOptions(int nQNum, int nOption)

{

String* pstrOpt; switch(nQNum)

{

case 1:

if (nOption == 1) pstrOpt = “6”;

else if (nOption == 2) pstrOpt = “5”;

else if (nOption == 3) pstrOpt = “7”;

break; case 2:

if (nOption == 1) pstrOpt = “55”;

else if (nOption == 2) pstrOpt = “50”;

else if (nOption == 3)

IMPLEMENTING REMOTING

Chapter 31

895

 

 

 

 

pstrOpt = “52”; break;

case 3:

if (nOption == 1) pstrOpt = “Russia”; else if (nOption == 2) pstrOpt = “India”; else if (nOption == 3) pstrOpt = “China”; break;

case 4:

if (nOption == 1) pstrOpt = “California”; else if (nOption == 2) pstrOpt = “New York”; else if (nOption == 3) pstrOpt = “Arizona”; break;

case 5:

if (nOption == 1) pstrOpt = “Mars”;

else if (nOption == 2) pstrOpt = “Saturn”; else if (nOption == 3) pstrOpt = “Jupiter”; break;

case 6:

if (nOption == 1) pstrOpt = “Mars”;

else if (nOption == 2) pstrOpt = “Mercury”; else if (nOption == 3) pstrOpt = “Earth”; break;

case 7:

if (nOption == 1)

pstrOpt = “North America”; else if (nOption == 2)

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

pstrOpt = “South America”; else if (nOption == 3) pstrOpt = “Europe”;

break; case 8:

if (nOption == 1) pstrOpt = “New Delhi”; else if (nOption == 2) pstrOpt = “Bombay”; else if (nOption == 3) pstrOpt = “Calcutta”; break;

case 9:

if (nOption == 1) pstrOpt = “Dollar”; else if (nOption == 2) pstrOpt = “Yuwan”; else if (nOption == 3) pstrOpt = “Yen”; break;

case 10:

if (nOption == 1) pstrOpt = “Germany”; else if (nOption == 2) pstrOpt = “France”; else if (nOption == 3) pstrOpt = “England”; break;

default:

if (nOption == 1) pstrOpt = “000”;

else if (nOption == 2) pstrOpt = “000”;

else if (nOption == 3) pstrOpt = “000”; break;

}

return pstrOpt;

IMPLEMENTING REMOTING

Chapter 31

897

 

 

 

 

}

//Sends the correct answer to the client int GetAnswer(int nNum)

{

int nAnswer; switch(nNum)

{

case 1: nAnswer = 3; break;

case 2: nAnswer = 3; break;

case 3: nAnswer = 1; break;

case 4: nAnswer = 1; break;

case 5: nAnswer = 3; break;

case 6: nAnswer = 2; break;

case 7: nAnswer = 2; break;

case 8: nAnswer = 1; break;

case 9: nAnswer = 3; break;

case 10: nAnswer = 2; break;

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

default: nAnswer = -1; break;

}

return nAnswer;

}

};

}

Creating the Remote Server Application

The remote object that we created in the preceding section is not complete. It requires a server application that will run continuously and monitor a particular port on a particular channel. (Refer to Chapter 30 for concepts related to channels.)

To the current solution, add a new Visual C++ project of the type Managed C++ application. Name the project as RemoteServer. The IDE will create the following files for you:

Stdafx.h

Stdafx.cpp

RemoteServer.cpp

AssemblyInfo.cpp

Open the file RemoteServer.cpp from the Solution Explorer. It will have the declaration for using the System namespace and the default implementation of the main function.

int _tmain(void)

{

return 0;

}

To implement the server, you need to perform the following steps:

1.Create a new object of the channel type you have decided to use and register the channel.

2.Declare the class in the RemoteObject as a type and register it as a wellknown type.

System::Run-

IMPLEMENTING REMOTING

Chapter 31

899

 

 

 

 

The RemoteServer application will need the classes in the Remoting, Channels, and Tcp, namespaces. Also, the application needs to access the RemoteObject class that is part of the nsRemoting namespace.

Add the following declarations to the file RemoteServer.cpp:

using namespace nsRemoting; using namespace System;

using namespace System::Runtime::Remoting;

using namespace System::Runtime::Remoting::Channels; using namespace System::Runtime::Remoting::Channels::Tcp;

Add the following code to the main function:

TcpChannel* pChannel2 = new TcpChannel(8085);

ChannelServices::RegisterChannel(pChannel2);

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

RemotingConfiguration::RegisterWellKnownServiceType(pType, “Quiz”,

WellKnownObjectMode::SingleCall);

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

Console::ReadLine();

return 0;

The ChannelServices class provides methods for registering remote channels. Channels are .NET mechanisms that are used to deliver messages across remoting boundaries such as machines, processes, and AppDomains. A channel can listen endlessly for an incoming message and send an outgoing message to a designated destination. Channels can provide the functionality to convert messages to and from a specific protocol. Channels are a part of the

time::Remoting::Channels namespace.

The TcpServerChannel is one of the two types of channels supported by .NET remoting. You can use this to set up the port number that you want the remote object to use, and the ChannelServices::RegisterChannel will bind that port number to the TCP/IP stack of the operating system.

TcpChannel* pChannel2 = new TcpChannel(8085);

ChannelServices::RegisterChannel(pChannel2);

You also have the option of using the HTTP channel. This can be done by using the

HttpServerChannel class in the System::Runtime::Remoting::Channels:Http

namespace.