Отправляет email-рассылки с помощью сервиса Sendsay
  Все выпуски  

Уроки по Visual C++ (MFC, платформа .NET)


Информационный Канал Subscribe.Ru

Visual C++. MFC. Уроки по программированию с сайта http://progs.biz

Рассылка №41

Visual C++. MFC. Урок 33. Классы MFC для работы с сетью.
Visual C++. MFC. Урок 34. Пишем сервер с использованием CSocket.

Полные версии уроков (с картинками) можно найти по адресам
Урок 33. Классы MFC для работы с сетью.
Урок 34. Пишем сервер с использованием CSocket.

Visual C++. MFC. Урок 33. Классы MFC для работы с сетью

Писать приложения, работающие на одном компьютере - интересно и замечательно. Но этот и пару последующих уроков мы с вами посвятим разработке сетевого приложения. Ничего особо ценного оно из себя представлять не будет - только самые простые сетевые функции. Оно сможет посылать некоторые данные (которые пользователь наберет в edit'е) на другой компьютер. Но, в общем, этого будет достаточно для разработки и более сложных сетевых приложений - ведь работа каждого такого приложения как раз и сводится к пересылке по сети некоторых данных.

Но прежде мы с вами обсудим классы MFC, предназначеные для работы с сетью.

Во-первых, это классы CSocket и CAsyncSocket. Они предназначены для работы с сетью посредством протокола TCP/IP. Оба они являются потомками класса CObject (класс CAsyncSocket непосредственный потомок класса CObject, а класс CSocket - потомок класса CAsyncSocket). Оба эти класса работают с данными на самом низком уровне (в библиотеке MFC, естественно) - т. е. они заняты пересылкой отдельных байтов. Разница между ними такая - при использовании класса CSocket приложение дожидается ответа от другого компьютера, т. е. работа программы блокируется, пока сетевая операция не завершится. Если же приложение использует класс CAsyncSocket, то клиент и сервер будут работать асинхронно (без взаимной блокировки).

Во-вторых, это целое семейство классов MFC, предназначенных для работы со стеком протоколов TCP/IP. Сюда относятся такие классы как CInternetSession (служит для создания и инициализации сессий), CInternetConnection (управляющий соединением с сервером) и производные от него классы CFtpConnection (соединение по протоколу FTP) и CHttpConnection (соединение по протоколу HTTP) и некоторые другие. Их мы будем рассматривать в последующих уроках.

Наверх

Visual C++. MFC. Урок 34. Пишем сервер с использованием CSocket

Приступаем непосредственно к созданию сетевого приложения. Работать оно сможет как в пределах одного, так и двух компьютеров. Соединение между клиентской и серверной частями будет происходить по протоколу TCP/IP. Если у вас только один компьютер, то в качестве адреса сервера клиент должен будет указать адрес 127.0.0.1. Этот адрес всегда показывает на ваш компьютер, что очень удобно при отладке сетевых прилжений.

На этом занятии мы напишем серверную часть нашего приложения. Запустите мастер MFC AppWizard и создайте с его помощью основанное на диалоге приложение. В качестве имени проекта наберите server. На шаге 2 обязательно поставьте галочку для поддержки Windows Sockets.

На этом же шаге можно убрать галочки для окошка About и для поддержки ActiveX'ов.

После создания заготовки для нашей программы разместите на форме одну кнопку (с идентификатором IDC_LISTEN и заголовком Listen) и один edit (с идентификатором IDC_DATA). При нажатии на кнопку Listen сервет начнет слушать сеть. После того, как клиент подсоединится к нашему серверу и отправит некоторые данные, они появятся в нашем edit'е. Для простоты после соединения только клиент сможет отправлять данные. Если вы захотите отправлять даные и с сервера, то вам придется добавить в серверную часть нашей программы код, аналогичный коду клиентской части (которую мы рассмотрим на следующем уроке).

К нашему edit'у (с идентификатором IDC_DATA) припишите с помощью ClassWizard'а переменную m_sData типа CString.

Приступаем непосредственно к написанию кода.

Создаем новый класс CMySocket как потомок класса CSocket.

Добавляем в него переменную типа указатель на CServerDlg:

public:
    CServerDlg* m_pDlg;

В этой переменной будет храниться указатель на наше диалоговое окно (так как в указателе на родительский класс можно хранить указатель на производный класс). Так как мы тут используем класс CServerDlg, то необходимо добавить строчку

class CServerDlg;

непосредственно перед объявлением класса CMySocket.

Далее мы должны добавть метод для задания переменной m_pDlg. Назовите его SetParentDlg. Реализация для него самая простая

void CMySocket::SetParentDlg(CServerDlg *pDlg)
{
    m_pDlg=pDlg; //Указатель на диалоговое окно
}

Теперь нам надо в нашем классе написать 2 виртуальные функции - OnAccept и OnReceive. Первая будет вызываться, когда наш слушающий сеть сокет получит запрос на соединение с клиентской стороны. Вторая - при получении данных от клиента. Для добавления виртуальной функции OnAccept щелкните на вкладке ClassView на классе CMySocket правой кнопкой мыши и выберите Add Virtual Function. В появившемся окне New Virtual Override for Class CMySocket двойным щелчком перенесите функции OnAccept и OnReceive в правый listbox и нажмите на OK.

В созданные заготовки для функций добавьте следующий код:

void CMySocket::OnAccept(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    AfxMessageBox("Соединение");
    m_pDlg->OnAccept();
    CSocket::OnAccept(nErrorCode);
}
void CMySocket::OnReceive(int nErrorCode)
{
    // TODO: Add your specialized code here and/or call the base class
    AfxMessageBox("Данные получены");
    m_pDlg->OnReceive();
    CSocket::OnReceive(nErrorCode);
}

В этих двух фрагментах мы после показа MessageBox'а (для наглядности процесса) вызываем одноименные функции нашего диалогового окна (через переменную m_pDlg, которая как раз и будет хранить указатель на главное окно). Эти функции диалогового окна у нас пока не написаны. Почему код по обработке лучше присать в классе диалогового окна, а не в классе сокета? Так как данные, в общем-то, пересылаются именно диалоговому окну, а не нашему сокету. Вот пусть диалоговое окно и разбирается. Но, в принципе, всю обработку можно было делать и в классе сокета. Так как мы в этом фрагменте используем переменную m_pDlg, то перед реализацией методов пишем строку

...
#include "ServerDlg.h"
 ...

Теперь займемся классом диалогового окна. Для начала задайте в нем две переменные типа CMySocket:

...
#include "MySocket.h"
 ...
class CServerDlg : public CDialog
{
public:
    CMySocket m_pListenSocket; //Слушающий сокет
    CMySocket m_pConnectSocket; //Передающий сокет
    ...

Обратите внимание на добавленый include - без него компилятор будет ругаться на строчки с двумя добавленными сокетами.

Как вы видите, сокетов у нас два. Первый (m_pListenSocket) - слушающий сокет. Когда серверная часть нашего приложения начинает работать, именно он слушает на определенном порту, не захочет ли какой-нибудь клиент подсоединится. Как только от клиента поступит запрос на подсоединение, то наш слушающий сокет m_pListenSocket переведет соединение на передающий сокет m_pConnectSocket, а сам будет продолжать слушать дальше (код по переводу соединения мы еще напишем). А передачей данных будет заниматься наш второй сокет - m_pConnectSocket.

Пишем код дальше. В методе OnInitDialog зададим значение для переменой m_pDlg сокетов (вызовом метода SetParentDlg):

BOOL CServerDlg::OnInitDialog()
{
    ...
    // TODO: Add extra initialization here
    m_pListenSocket.SetParentDlg(this);
    m_pConnectSocket.SetParentDlg(this);
    m_pListenSocket.Create(2000); //Создаем сокет на 200 порту
    return TRUE;  // return TRUE  unless you set the focus to a control
}

Таким образом переменная m_pDlg будет показывать на текущее диалоговое окно.

Далее пишем методы OnAccept и OnReceive:

void CServerDlg::OnAccept()
{
    //Переводим соединение на передающий сокет
    m_pListenSocket.Accept(m_pConnectSocket);
}

void CServerDlg::OnReceive()
{
    char *pBuf=new char[1025];
    //Записываем полученные данные в pBuf
    //Записываем в n количество полученных байтов
    int n=m_pConnectSocket.Receive(pBuf, 1024);
    //Отсекаем лишние символы
    pBuf[n]=NULL;
    //Записываем данные в переменную, связанную с edit'ом
    m_sData=pBuf;
    UpdateData(FALSE);
}

Теперь осталось написать код для кнопки Listen. Именно по нажатию на эту кнопку сокет m_pListenSocket начинает слушать сеть. Создайте обработчик для этой кнопки и добавьте в него следующий код:

void CServerDlg::OnListen()
{
    // TODO: Add your control notification handler code here
    m_pListenSocket.Listen(); //Сокет начинает слушать
}

С написанием сервера все! На следующем уроке мы напишем клиента.

Наверх

Другие рассылки с сайта progs.biz:

Рассылки Subscribe.Ru
Visual Basic. Уроки.
Уроки по C# и .NET.
  • Уроки по Visual Basic.NET с сайта progs.biz. Написание программ, создание собственных элементов, примеры и исходники, создание ActiveX-элементов, работа с базами данных, создание веб-приложений, FAQ и многое другое.
  • Уроки по C# -новому языку от Microsoft для платформы .NET. Примеры, исходники, статьи, FAQ.

Copyright Алексеев Игорь, 2002

Copyright cайт progs.biz, 2002



http://subscribe.ru/
E-mail: ask@subscribe.ru
Отписаться
Убрать рекламу

В избранное