Слайд 1КЛИЕНТ-СЕРВЕРНЫЕ ПРИЛОЖЕНИЯ
ПРОГРАММИРОВАНИЕ ПЕРЕДАЧИ ИНФОРМАЦИИ
МЕЖДУ КОМПЬЮТЕРАМИ ПО СЕТИ
Слайд 2Компьютер в сети называется узел (хост) и имеет уникальный адрес, который
называется IP (internrt pointer). IP – адрес состоит из 4 целых чисел от 0 до 255, разделенных точкой. Некоторые адреса имеют специальное назначение, например 127.0.0.1 –localhost – локальный адрес текущего компьютера.
192.168.XXX.XXX – адрес компьютера внутри локальной сети.
Но знать IP – адрес недостаточно, поскольку обмениваются информацией не компьютеры сами по себе, а приложения, работающие на них. Каждое программное приложение должно иметь свой номер – “номер порта”. Порт – это логическое соединение, через которое принимаются или отправляются данные.
Слайд 3Большинство стандартных приложений имеют стандартные но-мера, например почтовый сервис привязан к
порту 25 (как гово-рят «слушает порт 25»), веб-сервис привязан к порту 80, FTP – к 21 и т.д.
Номера портов до 1024 зарезервированы (заняты). Есть исключе-ния, например 3128 – порт прокси-сервера.
Передача информации между компьютерами (точнее между процессами) осуществляется через сокеты. Socket (гнездо, разъ-ем) с точки зрения программы – это объект, осуществляющий пе-ресылку данных с одного конца линии связи на другой, от одного процесса к другому.
Основными параметрами сокета являются номер компьютера и номер порта, эта комбинация идентифицирует сокет.
Слайд 4Компьютеры по сети обмениваются пакетами, которые содержат адрес отправителя, адрес получателя
и собственно данные (+слу-жебная информация).
Как правило взаимодействие осуществляется по схеме клиент-сервер: клиент запрашива-ет какую-либо информацию, а сервер принимает запрос, обрабатывает его и отсылает клиенту результат.
Обмен информацией по сети определяется протоколами. Протокол – это набор соглашений и правил обмена данными между программами. Протокол определяет очередность действий, позволяющую осуществлять соединение и обмен данными между устройствами и процессами. Порт – это один из пара- метров протокола.
Слайд 5Протоколы бывают разных уровней и работают друг с другом в стеке:
протокол, располагающийся на уровне выше, работает поверх нижнего.
Например: IP – протокол сетевого уровня. Задача этого уровня – доставка пакетов от компьютера-отправителя к компьютеру-по-лучателю. Номера портов на сетевом уровне не используются. Какому порту адресован пакет, был ли он доставлен, на этом уровне не известно.
TCP и UDP – протоколы транспортного уровня, они используют номер порта.
UDP – это протокол без установления соединения с негарантиро-ванной доставкой пакетов (типа: крикнул что-нибуь, а услышат тебя или нет – неважно). Сокеты, работающие по этому протоколу, называются дейтаграммные.
Слайд 6TCP – протокол с установлением соединения и гарантированной доставкой пакетов. Сначала
производится обмен специальными пакетами для установления соединения. Далее по этому соеди-нению туда и обратно отсылаются пакеты, причем с проверкой, дошел ли пакет до получателя. Если пакет не дошел, то он посы-лается повторно. Сооответствующие сокеты называются поточ-ными.
Над транспортным уровнем находится прикладной уровень. На этом уровне работают такие протоколы как http, ftp и другие.
Слайд 7ПРОТОКОЛ TCP
Сокет TCP может быть серверным или клиентским. Первый про-слушивает порт
с некоторым номером, ожидая подключения со стороны клиентов, а второй (со стороны клиента) пытается под-ключиться к серверному сокету.
Приняв запрос на подключение, процесс – сервер создает для нового клиента со своей стороны также клиентский сокет, через который продолжает общаться с клиентом.
Сокеты могут работать в блокирующем и неблокирующем ре-жиме.
Слайд 8В первом случае выполнение потока, в котором работает сокет, блоки-руется до
окончания выполнения очередной операции. Во втором случае используется программирование, управляемое событиями.
В библиотеке Qt для работы с сокетами имеется модуль QtNetwork, который необходимо подключит командой #include.
Перед компиляцией программы в файле проекта *pro необхо-димо добавить строку:
QT += network
Слайд 9АЛГОРИТМ РАБОТЫ С СЕРВЕРНЫМ СОКЕТОМ
Создать экземпляр класса QTcpServer;
Перевести сервер в слушающее
состояние.
Перевести сервер в состояние ожидания запроса на подключение.
Когда клиент подключился:
Создать сокет для связи с клиентом (с помощью класса QTcpSocket) и проинициализировать его.
Ждать прихода запроса от клиента.
Если данные пришли, прочитать их.
Слайд 10ПРИМЕР
Консольное приложение:
эхо-сервер в блокирующем режиме
Создать консольное приложение Qt.
стереть лишние команды
из файла main.cpp
файл main.cpp
#include
#include
#include
#define STR(s) ((codec->fromUnicode(s)).constData())
using namespace std;
Слайд 11int main(int, char**)
{
QTextCodec* codec = QTextCodec::codecForName("CP866");
//qDebug()
<< QString::fromUtf8("Проверка:\n").toLocal8Bit().data() << endl;
// qDebug() << "Отладка"; // Выводит в то же окно, что и cout
QTcpServer server;
server.listen(QHostAddress::Any, 1234);
cout << STR("Сервер запущен\n");
// каждые 5 сек выводится сообщение:
while (!server.waitForNewConnection(5000))
// все функции wait блокируют работу потока
cout << STR("Ожидание запроса на подключение клиента\n");
Слайд 12 QTcpSocket* client; // Клиентский сокет
QHostAddress addr; //
Адрес клиента
QByteArray block; // Блок для обмена данными
/*Для подтверждения соединения с клиентом необходимо вызвать метод nextPendingConnection(), который возвратит сокет, посредством кото-рого можно осуществлять дальнейшую связь с клиентом: */
client = server.nextPendingConnection(); //pending - ожидающий
// подключение произошло, создаем для него новый сокет:
addr = client->peerAddress(); // определяем адрес клиента
cout <
Слайд 13forever // позволяет повторить процесс получения строки
{
forever //
ожидание поступления данных
{
if (!client || !client->isValid() || client->state() == QAbstractSocket::UnconnectedState)
{
cout << STR("Клиент отключился\n");
return 0;
}
if (client->waitForReadyRead(1000))
// в течение 1 сек ждем прихода данных
{
block = client->readAll(); // считываем данные
cout << block.data()<< endl;
break;
}
}
Слайд 14 client->write(STR("Эхо: "));
client->write(block);
client->write("\n");
client->waitForBytesWritten();
}
return 0;
}
Слайд 15Консольное приложение: клиент
#include
#include
#include
#define STR(s) (codec->fromUnicode(s).constData())
using namespace std;
int
main(int , char **)
{
QTextCodec* codec = QTextCodec::codecForName("CP866");
Слайд 16 QTcpSocket socket;
QByteArray block;
QString server =
"127.0.0.1";
int port = 1234;
socket.connectToHost(server, port);
cout << STR("Клиент запущен\n");
forever
{
cout << STR("Введите строку\n");
char text[81];
cin.getline(text, 80);
socket.write(text);
socket.waitForBytesWritten();
Слайд 17 forever
{
if (socket.waitForReadyRead(1000))
{
block = socket.readAll();
cout << block.data();
break;
}
}
}
return 0;
}