Microsoft Visual C++ .NET Professional Projects - Premier Press
.pdf
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)
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.
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.
