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

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

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

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

Table 29-3 Methods for Conversion of Network Byte to Host Byte

Methods

public: static short NetworkToHostOrder(short); public: static int NetworkToHostOrder(int); public: static int64 NetworkToHostOrder (int64);

The Parse Method

Y L This method is used to create an instanceFof the IPAddress class from a string

containing an IP address. The syntax of the method is as follows:

public: static IPAddress* Parse(String *);

Threads play an important role in socket programming. Hence, knowledge about

 

 

M

the Thread class and its member functions is a must. The following section dis-

cuss the Thread class.

A

 

E

T

 

The System.Threading Namespace

The System.Threading namespace is used for developing multithreaded applications. It consists of classes for performing various tasks, such as scheduling, synchronizing, and resolving deadlock situations.

The Thread class in this namespace is discussed in the following section.

The Thread Class

Any task that has to run continuously as part of a process is coded in a thread. You can specify the priority for a particular thread as defined in ThreadPriority. In its entire life cycle, a thread keeps changing its state as defined by ThreadState.

To start the thread, you need to have the thread constructor that initializes the instance of the new thread. The constructor of the thread is defined as follows:

public: Thread(ThreadStart *);

The constructor accepts the thread handler method as a parameter.

Team-Fly®

IMPLEMENTING NETWORKING

Chapter 29

851

 

 

 

 

Some of the important properties of the Thread class are listed in Table 29-4.

Table 29-4 Important Properties of the Thread Class

Property

Description

CurrentThread

Sets or retrieves the name of the thread that is currently active

IsAlive

Sets or retrieves the status of a thread whether alive, aborted, or

 

terminated

IsBackground

Sets or retrieves whether the thread has to run in the background

Name

Sets or retrieves the name of a thread

Priority

Sets or retrieves the priority of a thread

ThreadState

Retrieves the current state of the thread

 

 

The following are the methods associated with the Thread class:

Start. Used to start the thread and keep it running until the thread is suspended or interrupted by another thread. The syntax is

public: void Start();

GetDomain. Returns the name of the domain on which the thread is currently running. The syntax is

public: static AppDomain* GetDomain();

Sleep. Used to block the thread for the number of milliseconds specified. The syntax is

public static void Sleep(int);

The syntax of the overloaded function is

public: static void Sleep(TimeSpan);

NOTE

Specify 0 as the TimeSpan value if you want to suspend the execution of a thread and infinite to make the thread run in an infinite loop.

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

Interrupt. Used to interrupt the thread in the WaitSleepJoin state. The syntax is

public: void Interrupt();

Suspend. Used to suspend the thread in the running state. The syntax is

public: void Suspend();

Resume. Used to get the thread resumed if it is suspended. The syntax is

public: void Resume();

Case Study

The project managers and the directors at Somic Software meet weekly to discuss and share the triumphs and tragedies of their projects. Because the project managers were dealing with clients from different geographical areas, getting all the project managers together at the same time for a meeting was becoming a problem.

To resolve this problem, one project manager came up with the idea of developing a chat application that would enable everybody to meet online whenever required. Other project managers appreciated the idea and the requirements document was prepared.

The following requirements were recognized at the initial stages:

Any text sent by any user should get displayed to all the users running the application.

The application should allow the users to save the chat.

The technical leader of the development team at Somic Software was given the task of developing the chat application using VC++.NET and releasing the first beta version within seven days.

I’ll quickly take you through the tasks performed in the different phases of the project life cycle and then explain the code involved.

IMPLEMENTING NETWORKING

Chapter 29

853

 

 

 

 

Project Life Cycle

The project life cycle for this application, as for most common applications, comprises the following phases:

Requirements analysis

Design

Construction

Testing

Requirements Analysis

In the requirements analysis phase, the programmers interviewed the director and discussed the need and rationale behind the application by asking some common questions:

What type of chat application is required?

How many people will chat at a time?

Should the users who are chatting appear in the list?

Do you require the option of disabling any user from receiving a particular message?

The team also met with the system administrator to discuss the type of network used in the office.

Design

After the requirements for the project had been analyzed, the team decided upon the functionality and the final output of the application. In addition, different aspects of the application to be developed, such as the interface, were also decided. Based on the decisions, the following functional implementations were decided upon:

List boxes that display the messages and users who are chatting

A textbox that allows the user to type the message

Three buttons: Send, Save, and Exit

Figure 29-2 shows the user-interface of the chat application.

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

FIGURE 29-2 The Chat Dialog interface

Construction

After the design phase is complete, you need to start coding the application. The steps to construct the application are as follows:

1.Create a new project by selecting File, New, Project.

2.In the New Project dialog box, select Visual C++ Projects in the Project Types area, select Managed C++ Application in the Templates area, type the location of your project in the Location box, and type the name of your project in the Name box, as shown in Figure 29-3.

FIGURE 29-3 New Project dialog box

IMPLEMENTING NETWORKING

Chapter 29

855

 

 

 

 

3.Create the ChatAppW.cpp and Chat.h files using the New option in the File menu.

Code the Project to Develop the Application

After you have completed creating the file, you need to start writing the code. In this section, I’ll walk you through the code to create a chat application.

I will explain the entire code by dividing it into functions and what they are expected to perform. To begin the code, open the file stdafx.h and include the following DLLs and namespaces required:

//stdafx.h : include file for standard system include files,

//or project specific include files that are used frequently, but

//are changed infrequently

#include <tchar.h>

#using <System.dll> #using <mscorlib.dll>

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

using namespace System; using namespace System::IO;

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

using namespace System::Net;

using namespace System::Net::Sockets; using namespace System::Threading; using namespace System::Text;

Table 29-5 explains the different namespaces included and their usage.

Table 29-5 Namespaces Included in the Code

Namespaces

Description

System::IO

Defines the classes for input and output operations

System::ComponentModel

Defines the classes that enable you to use the runtime

 

and design-time behavior of components and controls

 

continues

856

Project 10 NETWORKING AND REMOTING IN VC++.NET

 

 

 

 

 

 

 

Table 29-5 (continued)

 

 

 

 

 

 

 

 

Namespaces

Description

 

 

 

 

 

 

 

System::Windows::Forms

Defines the classes that enable you to create window-

 

 

 

 

based applications

 

 

System::Drawing

Defines the classes that provide GDI functionality, like

 

 

 

 

a brush and pen

 

 

System::Net

Provides a programming interface for many networking

 

 

 

 

protocols currently in use

 

 

System::Net::Sockets

Provides the implementation of Windows Sockets

 

 

System::Threading

Provides the classes and interfaces required to program

 

 

 

 

a multithreaded application

 

 

System::Text

Provides the classes required for encoding and decoding

 

 

 

 

the text

 

 

 

 

 

Next, consider the code written in the Chat.h file:

#pragma once #include “stdafx.h”

//Chat class defined __gc class CChat

{

//Private member variables

public:

//Public member variables

static IPAddress* m_pGroupAddress; static IPEndPoint* m_pRemoteEP; static int nListenerPort = 8000; static int nSenderPort = 8000; static bool m_bDone = false;

//For UDP network services

static UdpClient* m_pClient; static ListBox* m_pListBox;

static ListBox* m_pchkdLstBoxUserList;

IMPLEMENTING NETWORKING

Chapter 29

857

 

 

 

 

public:

//Constructor

CChat()

{

}

CChat(ListBox* pListBox, ListBox* pchkdLstBoxUserList)

{

m_pListBox = pListBox;

m_pchkdLstBoxUserList = pchkdLstBoxUserList;

}

//Destructor void ~CChat()

{

}

In the preceding code, a class CChat prefixed with __gc is created. The pointer m_pGroupAddress stores the IP address of the MulticastGroup and the pointer m_pRemoteEP stores the IP address of the MulticastGroup and the sender’s port number.

The variables nListenerPort and nSenderPort store the port number on which the data will be sent and received. The pointer to UdpClient will store the port number on which clients will listen.

Consider the following code that initializes data members and variables:

static String* GetChatHostName()

{

//Get the hostname of local computer return Dns::GetHostName();

}

IPEndPoint* GetRemoteEP()

{

return m_pRemoteEP;

}

IPAddress* GetGroupAddress()

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

{

return m_pGroupAddress;

}

//Initializes the UdpClient void Initialize()

{

m_pClient = new UdpClient(nListenerPort); m_pGroupAddress = IPAddress::Parse(“224.0.1.1”); try

{

//Adds a UdpClient to a multicast group m_pClient->JoinMulticastGroup(m_pGroupAddress, 50);

}

catch(Exception* ep)

{

m_pListBox->Items->Add(S”Unable to join multicast group”);

}

//m_pRemoteEP Represents a network endpoint

m_pRemoteEP = new IPEndPoint( m_pGroupAddress, nSenderPort);

}

void Terminate()

{

//Leaves a multicast group m_pClient->DropMulticastGroup(m_pGroupAddress);

}

In the preceding code, the method GetHostName() will return the local computer’s host name. GetRemoteEP() and GetGroupAddress() are user-defined methods that will return the IP address and network endpoint of the remote host.

The Initialize() method is used for initializing pointers and variables declared in the public section of the class. It also has system-defined methods, such as

Parse(), JoinMulticastGroup(), IPEndPoint(), and DropMulticastGroup(),

which were explained earlier in the chapter.

Consider the following code that encodes the data received from the remote host and displays it in the list box:

IMPLEMENTING NETWORKING

Chapter 29

859

 

 

 

 

static void Listener()

{

Thread::Sleep(2000);

Encoding* pASCII = Encoding::ASCII; while(m_bDone != true)

{

IPEndPoint* pEndPoint = NULL;

Byte bytearrayData [] = m_pClient->Receive(&pEndPoint);

String* pstrData = pASCII->GetString(bytearrayData);

Char cSeparators [] = {‘:’};

String* pVars [] = pstrData->Split(cSeparators); if( pstrData->IndexOf(S”:@”) > 0 )

{

String* pHostName = GetChatHostName(); if( pVars[0] == pHostName )

{

m_pListBox->Items->Add(S”Shutting down Listener thread...”);

}

else

{

String* pStr;

pStr = String::Format(“{0} has left the conversation”, pVars[0]); m_pListBox->Items->Add(pStr);

m_pListBox->Items->Add(S”Shutting down Listener thread...”);

}

//Remove this user from the “Logged On User:” list

int nItemIndex = m_pchkdLstBoxUserList->FindStringExact(pVars[0]); m_pchkdLstBoxUserList->Items->RemoveAt(nItemIndex);

}

else

{

int nItemIndex = m_pchkdLstBoxUserList->FindStringExact(pVars[0]); if (nItemIndex == ListBox::NoMatches)

{

m_pchkdLstBoxUserList->Items->Add(pVars[0]);

}

if((pstrData->IndexOf(“:”) > 0) && (nItemIndex > -1))