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

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

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

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

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

The Type class is an abstract class that represents type declarations, such as class, interface, enumeration, and so on. It allows you to add a declaration of a class or interface to be registered as a well-known object type.

A client application that has the URI of a registered well-known object can obtain a proxy for the object by registering the preferred channel (TCP or HTTP) with

 

 

 

Y

ChannelServices and then activating the object. For the remote object to be

 

 

L

enabled by the client in this way, the remote object must be registered using the

 

 

F

RegisterWellKnownServiceType method:

 

 

M

 

RemotingConfiguration::RegisterWellKnownServiceType(pType, “Quiz”,

WellKnownObjectMode::SingleCall);

 

 

A

 

The preceding line binds the remote object to the name that you want to use for

E

 

 

it. The following list presents a quick glance at the method’s parameters:

T

 

 

 

The first parameter, pType, is the object you are binding.

The second parameter, Quiz, is a string that is the name for the object on the TCP channel. Clients would refer to the object as tcp://8086/Quiz.

The third parameter, WellknownObjectMode::SingleCall, conveys to the container application what should happen when a client request comes in. If the parameter is set to SingleCall, then for each client, a separate instance of the object will be created. If it is set to Singleton, then all the clients use the same instance.

The server end of the Quiz Application is ready to run!

The following is the complete code for the RemoteServer application:

#include “stdafx.h” #include <tchar.h>

#using <mscorlib.dll>

#using <System.Runtime.Remoting.dll> #using <RemoteObj.dll>

using namespace nsRemoting;

using namespace System;

Team-Fly®

IMPLEMENTING REMOTING

Chapter 31

901

 

 

 

 

using namespace System::Runtime::Remoting;

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

// This is the entry point for this application int _tmain(void)

{

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;

}

Creating the Client Application

You will create the client application as a Managed C++ application. To the existing solution, add a new project of the type Managed C++ Application. Call it RemoteClient. The IDE will create the following files:

Stdafx.h

Stdafx.cpp

RemoteClient.cpp

AssemblyInfo.cpp

The client is a simple GUI application that will have the following:

Two buttons, Submit and Exit.

Three radio buttons to represent the three choices that the user can select.

This interface assumes all questions will have three options. It can be easily modified for greater flexibility.

You will be using classes under the Remoting namespace to connect to the remote server; therefore, you will have the following namespace declarations:

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

using namespace System::Runtime::Remoting;

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

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

Also, you will use the CQuiz class declared under the nsRemoting namespace; hence, the following declaration is required:

using namespace nsRemoting;

The first step is to create the user interface. To accomplish this, create a new class that derives from the Form class. This class will house the UI of the client application. Hence, declare the following variables:

__gc class CQuizForm : public Form

{

private:

Next, declare a variable to store the caption of the form and variables, two integers to store the width and height of the client form, and two Label type variables to display the question number and the question:

String* pCaption;

int nWidth;

int nHeight;

Label* pLblQuestion;

Label* pLblQNum;

Add three radio buttons to display the answers, and two Button type variables for the Submit and the Exit buttons:

RadioButton* pRadioOpt1;

RadioButton* pRadioOpt2;

RadioButton* pRadioOpt3;

Button *pBtnSubmit;

Button *pBtnExit;

CQuizServer is the remote server class that is declared in the nsRemoting namespace. Next, you need to implement the constructor of the form. The client needs to obtain a reference to the remote server:

m_pQuizServer = (CQuizServer*)

Activator::GetObject(__typeof(nsRemoting::CQuizServer),

IMPLEMENTING REMOTING

Chapter 31

903

 

 

 

 

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

Next, initialize the user-interface elements. First, take a look at the basic settings for the main form:

//set the caption

Text = pCaption;

//set the size of the form

Size = Drawing::Size(nWidth, nHeight);

//disable the maximize box. set_MaximizeBox(false);

The form has two labels. The following is the code for one of the label controls:

pLblQNum = new Label(); pLblQNum->Text = “Question No. 1”;

pLblQNum->Size = Drawing::Size(100, 15); pLblQNum->BorderStyle = BorderStyle::FixedSingle; pLblQNum->Location = Drawing::Point(15, 15); pLblQNum->set_ForeColor(Color::Red);

Take a look at how to configure a radio button:

pRadioOpt1 = new RadioButton(); pRadioOpt1->Text = “Option1”; pRadioOpt1->TabIndex = 1;

pRadioOpt1->Size = Drawing::Size(250, 20); pRadioOpt1->Location = Drawing::Point(30, 90); pRadioOpt1->Visible = false;

While configuring a Button, you need to specify the event handler for any of its events. In case of a Button, you would want a method to do something on the Click event, and so create a new EventHandler object for this purpose:

pBtnSubmit = new Button(); pBtnSubmit->Text = “&Start”; pBtnSubmit->TabIndex = 4; pBtnSubmit->Size = Drawing::Size(55, 20);

pBtnSubmit->Location = Drawing::Point(80, 180);

pBtnSubmit->Click += (new EventHandler(this, &CQuizForm::OnSubmitButtonClick));

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

The last step is to add all the controls you have created to the Controls collection of the form:

Controls->Add(pLblQNum);

Next, examine what the event handler method for the Submit button is coded to do. This method retrieves the correct answer to a question and compares it with the option selected by the user. If they are the same, a variable bCorrect is set to

true.

void OnSubmitButtonClick (Object *sender, EventArgs *e)

{

int nResult = m_pQuizServer->GetAnswer(m_nQNum - 1); bool bCorrect = false;

switch(nResult)

{

case 1:

if (pRadioOpt1->get_Checked()) bCorrect = true;

break; case 2:

if (pRadioOpt2->get_Checked()) bCorrect = true;

break; case 3:

if (pRadioOpt3->get_Checked()) bCorrect = true;

break;

}

//If the answer is correct increment the score and display a message. if ( bCorrect )

{

MessageBox::Show(“Correct Answer”, “Result”); m_nCorrect++;

}

else

{

MessageBox::Show(“Incorrect Answer”, “Result”);

IMPLEMENTING REMOTING

Chapter 31

905

 

 

 

 

}

}

Check if all the questions have been asked, and if so, display an appropriate message depending on the score:

if (m_nQNum > 10)

{

return;

}

If questions remain, then reset all the radio buttons, get the next question from the server, and display the options:

pRadioOpt1->set_Checked(false); pRadioOpt2->set_Checked(false); pRadioOpt3->set_Checked(false);

String* pstrQuestion = m_pQuizServer->GetNextQuestion(m_nQNum); pLblQuestion->Text = pstrQuestion;

For each option, you need to query the RemoteServer to get the set of answers. Since all questions will have three answers, you can retrieve the answers using a for loop:

for (int i=1; i<4; i++)

{

String* pstrOpt = m_pQuizServer->GetOptions(m_nQNum, i); if (i == 1)

pRadioOpt1->Text = pstrOpt; else if (i == 2) pRadioOpt2->Text = pstrOpt; else if (i == 3) pRadioOpt3->Text = pstrOpt;

}

m_nQNum++;

}

That completes our discussion of the RemoteClient application.

As you saw, the syntax for accessing services from a remote server is not very different from the way you access a local assembly and from a similar application that uses DCOM. But, remember that the plumbing provided by the .NET platform as Remoting is very different from DCOM in the COM+ platform.

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

The following is the complete code for the client application:

#include “stdafx.h” #include <tchar.h>

#using <mscorlib.dll>

#using <System.dll>

#using <System.Windows.Forms.dll> #using <System.Drawing.dll>

#using <System.Runtime.Remoting.dll> #using “RemoteObj.dll”

using namespace System;

using namespace System::Runtime::Remoting;

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

using namespace System::ComponentModel; using namespace System::Windows::Forms; using namespace System::Drawing;

using namespace nsRemoting;

//////////////////////////////////////////////////

//Quiz Form Class

__gc class CQuizForm : public Form

{

private:

String* pCaption; // Caption of the CQuizForm

int

nWidth;

// Width of the CQuizForm

int

nHeight;

// height of the CQuizForm

Label* pLblQuestion;

Label* pLblQNum;

RadioButton* pRadioOpt1;

RadioButton* pRadioOpt2;

RadioButton* pRadioOpt3;

Button *pBtnSubmit;

Button *pBtnExit;

IMPLEMENTING REMOTING

Chapter 31

907

 

 

 

 

//TcpChannel* m_pChannel; CQuizServer* m_pQuizServer;

int m_nQNum; int m_nCorrect;

bool bButttonReset; String* m_pUserName;

public:

CQuizForm()

{

pCaption = “Quiz Dialog”; nWidth = 300;

nHeight = 240; bButttonReset = false; m_nQNum = 1; m_nCorrect = 0;

//Registers the channel for communication with Server //RegisterChannel();

m_pQuizServer = (CQuizServer*) Activator::GetObject(__typeof(nsRemoting::CQuizServer), “tcp://localhost:8085/Quiz”);;

//Do the intialization

InitForm();

}

void ~CQuizForm()

{

// Form is being destroyed. Do any necessary cleanup here. Form::Dispose();

}

void InitForm()

{

// Basic WinForm Settings

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

Text = pCaption;

Size = Drawing::Size(nWidth, nHeight); set_MaximizeBox(false);

pLblQNum = new Label(); pLblQNum->Text = “Question No. 1”;

pLblQNum->Size = Drawing::Size(100, 15); pLblQNum->BorderStyle = BorderStyle::FixedSingle; pLblQNum->Location = Drawing::Point(15, 15); pLblQNum->set_ForeColor(Color::Red);

pLblQuestion = new Label(); pLblQuestion->Text=”Question appears here “; pLblQuestion->Size = Drawing::Size(260, 40); pLblQuestion->BorderStyle = BorderStyle::FixedSingle; pLblQuestion->Location = Drawing::Point(15, 40);

pLblQuestion->set_TextAlign(ContentAlignment::MiddleCenter); pLblQuestion->set_ForeColor(Color::Blue);

pRadioOpt1 = new RadioButton(); pRadioOpt1->Text = “Option1”; pRadioOpt1->TabIndex = 1;

pRadioOpt1->Size = Drawing::Size(250, 20); pRadioOpt1->Location = Drawing::Point(30, 90); pRadioOpt1->Visible = false;

pRadioOpt2 = new RadioButton(); pRadioOpt2->Text = “Option2”; pRadioOpt2->TabIndex = 2;

pRadioOpt2->Size = Drawing::Size(250, 20); pRadioOpt2->Location = Drawing::Point(30, 115); pRadioOpt2->Visible = false;

pRadioOpt3 = new RadioButton(); pRadioOpt3->Text = “Option3”; pRadioOpt3->TabIndex = 3;

pRadioOpt3->Size = Drawing::Size(250, 20); pRadioOpt3->Location = Drawing::Point(30, 140); pRadioOpt3->Visible = false;

pBtnSubmit = new Button();

IMPLEMENTING REMOTING

Chapter 31

909

pBtnSubmit->Text = “&Start”;

 

 

 

 

 

 

pBtnSubmit->TabIndex = 4;

 

 

 

pBtnSubmit->Size = Drawing::Size(55, 20);

 

 

 

pBtnSubmit->Location = Drawing::Point(80, 180);

 

 

 

pBtnSubmit->Click += (new EventHandler(this, &CQuizForm::OnSubmitButtonClick));

pBtnExit = new Button(); pBtnExit->Text = “E&xit”; pBtnExit->TabIndex = 5;

pBtnExit->Size = Drawing::Size(55, 20);

pBtnExit->Location = Drawing::Point(165, 180);

pBtnExit->Click += (new EventHandler(this, &CQuizForm::OnExitButtonClick));

Controls->Add(pLblQNum);

Controls->Add(pLblQuestion);

Controls->Add(pRadioOpt1);

Controls->Add(pRadioOpt2);

Controls->Add(pRadioOpt3);

Controls->Add(pBtnSubmit);

Controls->Add(pBtnExit);

//Set the pBtnSubmit as the default

Form::set_AcceptButton(pBtnSubmit); pLblQNum->Visible = false;

//Display the welcome message

String* pstrWelcome = m_pQuizServer->DoWelcome(“ BUDDY!”);

pstrWelcome = String::Concat(pstrWelcome, “\nPlease press Start button to start the Quiz.”);

pLblQuestion->Text = pstrWelcome;

}

//Handles the Next button

void OnSubmitButtonClick (Object *sender, EventArgs *e)

{

if (!bButttonReset)

{

pBtnSubmit->Text = “&Submit”; pLblQNum->Visible = true;