C++ C++ C# C# ASP.NET Security ASP.NET Security ASM ASM Скачать Скачать Поиск Поиск Хостинг Хостинг  
  Программа для работы с LPT портом...
Язык: .NET — ©Alexey...
  "ASP.NET Atlas" – AJAX в исполнении Micro...
Язык: .NET — ©legigor@mail.ru...
  "Невытесняющая" Многопоточность...
Язык: C/C++ — ©...
  01.05.2010 — Update World C++: Сборник GPL QT исходников
  15.12.2007 — Весь сайт целиком можно загрузить по ссылкам из раздела Скачать
Хостинг:
Windows 2003, ASP.NET 2.0
бесплатный и от 80 руб./мес


   Отправить письмо
Кулабухов Артем, Беларусь




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

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

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

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

Шаг 2

На этом же шаге можно убрать галочки для окошка 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); //Создаем сокет на 2000 порту
    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(); //Сокет начинает слушать
}

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