c++ stl & qt. Занятие 07

36
Темы лекции: Работа с сетью в Qt. Практическое задание: Клиент-серверное приложение. Тренер: Игорь Шкулипа, к.т.н. С++ Библиотеки STL и Qt. Занятие 7

Upload: igor-shkulipa

Post on 06-Apr-2017

278 views

Category:

Education


1 download

TRANSCRIPT

Page 1: C++ STL & Qt. Занятие 07

Темы лекции: Работа с сетью в Qt.

Практическое задание: Клиент-серверное приложение.

Тренер: Игорь Шкулипа, к.т.н.

С++ Библиотеки STL и Qt. Занятие 7

Page 2: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 2

Протокол FTPFTP (File Transfer Protocol, протокол передачи файлов) — наиболее

известный из старых протоколов и являющийся одной из первых сетевыхслужб. Целью создания этого протокола было предоставлениепользователям доступа к файлам на удаленном компьютере.

FTP отличается от других протоколов тем, что он использует два TCPсоединения для передачи файла.

• Управляющее соединение устанавливается как обычное соединениеклиент-сервер. Сервер осуществляет пассивное открытие на заранееизвестный порт FTP (21) и ожидает запроса на соединение от клиента.Клиент осуществляет активное открытие на TCP порт 21, чтобыустановить управляющее соединение. Управляющее соединениесуществует все время, пока клиент общается с сервером. Этосоединение используется для передачи команд от клиента к серверу идля передачи откликов от сервера. Тип IP сервиса для управляющегосоединения устанавливается для получения "минимальнойзадержки", так как команды обычно вводятся пользователем.

• Соединение данных открывается каждый раз, когда осуществляетсяпередача файла между клиентом и сервером. Тип сервиса IP длясоединения данных должен быть "максимальная пропускнаяспособность", так как это соединение используется для передачифайлов.

Page 3: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 3

Схема работы FTP

Page 4: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 4

Команды FTPКоманды и отклики передаются по управляющему соединению между

клиентом и сервером в формате ASCII. В конце каждой строки командыили отклика присутствует пара CR, LF.

Команда Описание

ABOR прервать предыдущую команду FTP и любую передачу данных

LIST список файлов список файлов или директорий

PASS пароль пароль на сервере

PORT

n1,n2,n3,n4,n5,n6

IP адрес клиента (n1.n2.n3.n4) и порт (n5 x 256 + n6)

QUIT закрыть соединение на сервере

RETR имя файла получить (get) файл

STOR имя файла положить (put) файл

SYST сервер возвращает тип системы

TYPE тип указать тип файла: A для ASCII, I для двоичного

USER имя имя пользователя на сервере

Page 5: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 5

Отклики FTP

Отклики состоят из 3-циферных значений в формате ASCII, и необязательныхсообщений, которые следуют за числами. Подобное представление откликовобъясняется тем, что программному обеспечению необходимо посмотреть толькоцифровые значения, чтобы понять, что ответил процесс, а дополнительнуюстроку может прочитать человек.

Отклик Описание

1yz Положительный предварительный отклик. Действие началось, однако необходимо дождаться еще одного отклика перед отправкой следующей команды.

2yz Положительный отклик о завершении. Может быть отправлена новая команда.

3yz Положительный промежуточный отклик. Команда принята, однако необходимо отправить еще одну команду.

4yz Временный отрицательный отклик о завершении. Требуемое действие не произошло, однако ошибка временная, поэтому команду необходимо повторить позже.

5yz Постоянный отрицательный отклик о завершении. Команда не была воспринята и повторять ее не стоит.

x0z Синтаксическая ошибка.

x1z Информация.

x2z Соединения. Отклики имеют отношение либо к управляющему, либо к соединению данных.

x3z Аутентификация и бюджет. Отклик имеет отношение к логированию или командам, связанным с бюджетом.

x4z Не определено.

x5z Состояние файловой системы.

Page 6: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 6

Команды доступа к файлам

Протокол имеет целый ряд команд, с помощью которых можно управлятьудаленным компьютером для передачи данных:

• get — скопировать файл с удаленного сервера;• put — копировать файл на удаленный сервер;• rmdir — удалить каталог на удаленном сервере;• mkdir — создать каталог на удаленном сервере;• cd — открыть каталог на удаленном сервере;• rename — переименовать файл или каталог на удаленном

сервере;• close — закрыть соединение с удаленным сервером.

Page 7: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 7

FTP в Qt

Класс QFtp реализует сторону клиента FTP-протокола и содержит в себеметоды для наиболее часто используемых операций с FTP.

Названия этих методов соответствуют названиям FTP-команд, например: get()соответствует команде get, a put () — команде put и т. д.

Также класс QFtp предоставляет возможность исполнения любых FTP-команд.Для этого в метод rawCommand() нужно передать строку, содержащуюнужную команду.

Например:

ftp.rawCommand("MKDIR MyDir");

Класс QFtp содержит методы для осуществления соединения с FTP-серверомconnectToHost(), login() и т.д.

QFile file("index.txt");

QFtp ftp;

if (file.open(QIODevice::WriteOnly)) {

ftp.connectToHost("ftp.microsoft.com");

ftp.login();

ftp.cd("Softlib");

ftp.get("index.txt", &file);

ftp.close();

file.close();

}

Page 8: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 8

Протокол HTTP

HTTP (HyperText Transfer Protocol, протокол передачи гипертекста) – этопротокол прикладного уровня, разработанный для обменагипертекстовой информацией в Internet.

HTTP предоставляет набор методов для указания целей запроса,отправляемого серверу. Эти методы основаны на дисциплине ссылок,где для указания ресурса, к которому должен быть применен данныйметод, используется универсальный идентификатор ресурсов(Universal Resource Identifier, URI) в виде местонахождения ресурса(Universal Resource Locator, URL) или в виде его универсальногоимени (Universal Resource Name, URN).

Page 9: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 9

Протокол HTTP

HTTP используется для коммуникаций между различными пользовательскимипрограммами и программами-шлюзами, предоставляющими доступ ксуществующим Internet-протоколам.

Сообщения по сети при использовании протокола HTTP передаются в формате,схожем с форматом почтового сообщения Internet (RFC-822) или сформатом сообщений MIME (Multiperposal Internet Mail Exchange).

Протокол реализует принцип запрос/ответ. Клиент инициирует взаимодействиесервером и посылает запрос, содержащий:

• метод доступа;• адрес URI;• версию протокола;• сообщение с информацией о типе передаваемых данных, информацией

о клиенте, пославшем запрос, и, возможно, с телом сообщения.

Ответ сервера содержит:

• строку состояния, в которую входит версия протокола и код возврата(успех или ошибка);

• сообщение, в которое входит информация сервера, метаинформация(т.е. информация о содержании сообщения) и тело сообщения.

Page 10: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 10

Форма запроса

Клиент отсылает серверу запрос в одной из двух форм: в полной илисокращенной. Запрос в первой форме называется соответственнополным запросом, а во второй форме – простым запросом.

В качестве метода могут быть указаны GET, POST, HEAD, PUT, DELETE идругие.

В качестве запрашиваемого URI чаще всего используется URL-адресресурса.

Пример простого запроса:

GET http://somewebsite.com/

Здесь GET – это метод доступа, т.е. метод, который должен бытьприменен к запрашиваемому ресурсу, а http://somewebsite.com/ – этоURL-адрес запрашиваемого ресурса.

Полный запрос содержит строку состояния, несколько заголовков(заголовок запроса, общий заголовок или заголовок содержания) и,возможно, тело запроса.

Page 11: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 11

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

Метод сообщает о цели запроса клиента. Протокол HTTPподдерживает достаточно много методов, но реально используютсятолько три: POST, GET и HEAD.

Метод GET позволяет получить любые данные, идентифицированные спомощью URI в запросе ресурса. Если URI указывает на программу, товозвращается результат работы программы, а не ее текст (если,конечно, текст не есть результат ее работы). Дополнительнаяинформация, необходимая для обработки запроса, встраивается в самзапрос (в строку статуса).

При использовании метода GET в поле тела ресурса возвращаетсясобственно затребованная информация (текст HTML-документа,например).

Существует разновидность метода GET – условный GET. Этот методсообщает серверу о том, что на запрос нужно ответить, только есливыполнено условие, содержащееся в поле if-Modified-Since заголовказапроса. Если говорить более точно, то тело ресурса передается вответ на запрос, если этот ресурс изменялся после даты, указанной вif-Modified-Since.

Page 12: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 12

Методы HEAD и POST

Метод HEAD аналогичен методу GET, только не возвращает тело ресурсаи не имеет условного аналога. Метод HEAD используют для полученияинформации о ресурсе. Это может пригодиться, например, прирешении задачи тестирования гипертекстовых ссылок.

Метод POST разработан для передачи на сервер такой информации, каканнотации ресурсов, новостные и почтовые сообщения, данные длядобавления в базу данных, т.е. для передачи информации большогообъема и достаточно важной. В отличие от методов GET и HEAD, вPOST передается тело ресурса, которое и является информацией,получаемой из полей форм или других источников ввода.

Page 13: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 13

Другие методы HTTP-запросов

Метод Описание

PUT Сохранить веб-страницу

DELETE Удалить веб-страницу

TRACE Отослать назад запрос

CONNECT Рассчитан на работу с HTTPS протоколом

OPTIONS Отобразить параметры

Page 14: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 14

HTTP в Qt

Qt предоставляет класс QHttp для реализации стороны клиента HTTP-протокола. Использование этого класса очень похоже наиспользование класса QFtp.

Пример демонстрирует запись растрового изображения, находящегося наwww.geocities.ru/mslerm/images, в текущую директорию под именемqtbook.gif.

QFile file("book.gif");

QHttp http;

if (file.open(QIODevice::WriteOnly))

{

http.setHost("www.geocities.com");

http.get("/mslerm/images/qtbook.gif", &file);

http.close();

file.close();

}

Page 15: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 15

Протокол UDP

UDP (User Datagram Protocol, Протокол дейтаграмм пользователя)предназначен для обмена дейтаграммами между процессами компьютеров,входящих в единую сеть с коммутацией пакетов. В качестве протоколанижнего уровня UDP-протокол использует IP.

Протокол UDP предоставляет прикладным программам возможность отправлятьсообщения другим приложениям, используя минимальное количествопараметров протокола. Этот протокол не обеспечивает достоверностьдоставки пакетов, защиты дублирования данных или надежности от сбоев впередаче. За исключением параметров приложения - номеров портовотправителя и получателя пакета, UDP практически ничего не добавляет кIP-дейтаграмме.

Протокол UDP намного проще, чем TCP и полезен в ситуациях, когда мощныемеханизмы обеспечения надежности протокола TCP не требуются или будуттолько помехой для решения определенного рода задач, например,аутентификации пользователей.

Преимущество протокола UDP состоит в том, что он требует минимум установоки параметров для соединения двух процессов между собой. Этот протоколиспользуется при работе Серверов Доменов (Name Servers), при работепротокола TFTP (Trivial File Transfer, Тривиальный протокол передачиданных), работе с SNMP и построении систем аутентификации.

Page 16: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 16

Структура UDP пакета

• Source Port (16 бит). Порт отправителя. Это поле может содержатьномер порта, с которого был отправлен пакет, когда это имеетзначение (например отправитель ожидает ответа). Если это поле неиспользуется, оно заполняется нулями.

• Destination Port (16 бит). Порт назначения - это порт компьютера, накоторый пакет будет доставлен.

• Length (16 бит). Поле длины. Длина (в байтах) этой дейтаграммы,включая заголовок и данные. (Минимальное значение этого поляравно 8).

• Checksum (16 бит). Поле контрольной суммы. Контрольная суммаUDP-пакета представляет собой побитное дополнение 16-битнойсуммы 16-битных слов (аналогично TCP). В вычислении участвуют:данные пакета, заголовок UDP-пакета, псевдозаголовок (информацияот IP-протокола), поля выравнивания по 16-битной границе(нулевые).

Page 17: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 17

Структура UDP пакета

Page 18: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 18

UDP в Qt

Qt предоставляет класс QUdpSocket для реализации обменадатаграммами по протоколу UDP. Обмен датаграммами реализован ввиде методов readDatagram() и writeDatagram().

Пример:

QUdpSocket* udpSocket = new QUdpSocket(this);

udpSocket->bind(QHostAddress::LocalHost, 7755);

connect(udpSocket, SIGNAL(readyRead()),

this, SLOT(readPendingDatagrams()));

while (udpSocket->hasPendingDatagrams()) {

QByteArray datagram;

datagram.resize(udpSocket->pendingDatagramSize());

QHostAddress sender;

quint16 senderPort;

udpSocket->readDatagram(datagram.data(),

datagram.size(), &sender, &senderPort);

DoSomethingWithDatagram(datagram);

}

Page 19: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 19

Протокол TCP

Протокол TCP (Transmission Control Protocol, Протокол контроля передачи)обеспечивает сквозную доставку данных между прикладными процессами,запущенными на узлах, взаимодействующих по сети.

TCP - надежный байт-ориентированный (byte-stream) протокол сустановлением соединения. TCP находится на транспортном уровне стекаTCP/IP, между протоколом IP и собственно приложением. Протокол IPзанимается пересылкой дейтаграмм по сети, никак не гарантируя доставку,целостность, порядок прибытия информации и готовность получателя кприему данных; все эти задачи возложены на протокол TCP.

При получении дейтаграммы, в поле Protocol которой указан код протоколаTCP (6), модуль IP передает данные этой дейтаграммы модулю TCP. Этиданные представляют собой TCP-сегмент, содержащий TCP-заголовок иданные пользователя (прикладного процесса). Модуль TCP анализируетслужебную информацию заголовка, определяет, какому именно процессупредназначены данные пользователя, проверяет целостность и порядокприхода данных и подтверждает их прием другой стороне. По мереполучения правильной последовательности неискаженных данныхпользователя они передаются системному процессу.

Page 20: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 20

Схема работы TCP

Page 21: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 21

Сокетное соединение

Сокет — это устройство пересылки данных с одного конца связи надругой. Другой конец может принадлежать процессу, работающему налокальном компьютере, а может располагаться и на удаленномкомпьютере, подключенному к Интернету и расположенному в другомполушарии Земли. Сокетное соединение — это соединение типа точка-точка (point to point), которое производится между двумя процессами.

Класс QTcpSocket содержит набор методов для работы с TCP. С егопомощью можно реализовать поддержку для стандартных сетевыхпротоколов, таких как: HTTP, FTP, POP3, SMTP, и даже для своихсобственных протоколов. Этот класс унаследован от классаQAbstractSocket, который, в свою очередь, наследует классQIODevice. А это значит, что для доступа (чтения и записи) к егообъектам необходимо применять все методы класса QIODevice ииспользовать классы потоков QDataStream или QTextStream.

Работа класса QTcpSocket асинхронна, что дает возможностьизбежать блокирования приложения в процессе его работы.

Page 22: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 22

Пример «Чат». Сервер.

IView (MainWindow)

ChatServerPresenter

ChatServer

ChatMessage

ChatMessage

Page 23: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 23

Класс сервера

class ChatServer: public QObject

{

Q_OBJECT

public:

ChatServer(int port);

// Запуск сервера и связывание сигналов с методами

void Run();

// Очередь сообщений пуста

bool NoMessages();

// Возвращает первое сообщение из очереди

ChatMessage GetMessage();

public:

// Отключить клиента

void DisconnectClient();

// Подключить клиента

void ConnectNewClient();

// Получить сообщения от всех клиентов и добавить в очередь

void ReadClients();

// Отправить сообщение всем клиентам

void SendAll(ChatMessage message);

Page 24: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 24

Класс сервера

private slots:

void emitClientDisconnect();

void emitClientConnect();

void emitClientRead();

signals:

void chatServerStarted();

void chatClientRead();

void chatClientConnect();

void chatClientDisconnect();

private:

int port;

QList<QTcpSocket*> clients;

QTcpServer server;

QQueue<ChatMessage> messageQueue;

static const QString SRV_NAME;

static const QString MSG_CONNECTIONCLOSED;

static const QString MSG_STARTED;

};

Page 25: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 25

Интерфейс вида и окно приложения

class IView

{

public:

virtual void AddMessage(ChatMessage message)=0;

};

namespace Ui {

class MainWindow;

}

class MainWindow : public QMainWindow, public IView

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

virtual void AddMessage(ChatMessage message);

~MainWindow();

private:

Ui::MainWindow *ui;

static const QString MSG_DELIMITER;

};

Page 26: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 26

Презентер сервера

class ChatServerPresenter: public QObject

{

Q_OBJECT

public:

ChatServerPresenter(IView* view);

private slots:

void handleClientConnect();

void handleClientDisconnect();

void handleClientRead();

void handleServerStarted();

private:

IView* view;

ChatServer* chatServer;

};

Page 27: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 27

Класс сообщения (общий для сервера и клиента)

class ChatMessage

{

public:

ChatMessage();

ChatMessage(QString user, QString message);

QString ToString();

void FromString(QString str);

QString GetUser();

QString GetMessage();

QString GetTime();

private:

QString user;

QString message;

QString time;

static const QString MSG_DELIMITER;

};

Page 28: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 28

Пример «Чат». Клиент.

IView (MainWindow)

ChatClientPresenter

ChatClient

ChatMessage

ChatMessage

Page 29: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 29

Класс клиента

class ChatClient: public QObject

{

Q_OBJECT

public:

ChatClient(QString serverAddress, int serverPort);

ChatMessage getMessage();

void sendToServer(ChatMessage mess);

signals:

void messageReceived();

private slots:

void readFromServer();

private:

QTcpSocket* socket;

ChatMessage message;

};

Page 30: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 30

Интерфейс вида и окно приложения

class IView

{

public:

virtual void AddMessage(ChatMessage mess)=0;

virtual ChatMessage GetMessage()=0;

public:

virtual void messageInput()=0;

protected:

ChatMessage message;

};class MainWindow : public QMainWindow, public IView

{

Q_OBJECT

public:

explicit MainWindow(QWidget *parent = 0);

~MainWindow();

virtual void AddMessage(ChatMessage message);

virtual ChatMessage GetMessage();

signals:

void messageInput();

private slots:

void on_pushButton_clicked();

private:

Ui::MainWindow *ui;

QString MSG_DELIMITER;

};

Page 31: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 31

Презентер клиента

class ChatClientPresenter: public QObject

{

Q_OBJECT

public:

ChatClientPresenter(ChatClient* cl, IView* v);

ChatClientPresenter(IView* v);

private slots:

void DisplayMessage();

void SendMessage();

private:

ChatClient* client;

IView* view;

};

Page 32: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 32

Класс сообщения (общий для сервера и клиента)

class ChatMessage

{

public:

ChatMessage();

ChatMessage(QString user, QString message);

QString ToString();

void FromString(QString str);

QString GetUser();

QString GetMessage();

QString GetTime();

private:

QString user;

QString message;

QString time;

static const QString MSG_DELIMITER;

};

Page 33: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 33

Результат

Page 34: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 34

Результат

Page 35: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 35

Результат

Page 36: C++ STL & Qt. Занятие 07

http://www.slideshare.net/IgorShkulipa 36

Лабораторная работа №7. Клиент-серверный тетрис

Реализовать «клиент-серверный тетрис».

Функции сервера:• хранение базы данных игроков (лабораторная работа №5)• обработка авторизации/регистрации• прием, обработка и добавление в базу локальных данных игроков

в формате XML (лабораторная работа №6)

Функции клиента:• игра• авторизация/регистрация• соединение с сервером и отправка данных• если сервер недоступен, то сохранение статистики игры в XML• при возобновлении соединения – отправка XML на сервер