© EVILEG 2015-2018
Рекомендует хостинг
TIMEWEB

Qt/C++ - Урок 034. Echo Server на основе QTcpServer

ECHO, ECHO server, Qt, QTcpServer, QTcpSocket

Для работы со стеком TCP/IP Qt предоставляет классы QTcpServer, QTcpSocket, а также QUdpSocket. Для первого знакомства с работой локальной сети напишем Echo Сервер . Задача эхо сервера отправлять назад к отправителю полученные от него данные, как это делает эхо с человеческим голосом. Для подключения к серверу будет использоваться telnet.

TELNET (англ.  TErminaL NETwork) — сетевой протокол для реализации текстового интерфейса по сети (в современной форме — при помощи транспорта TCP). Название «telnet» имеют также некоторые утилиты, реализующие клиентскую часть протокола.

В предлагаемой программе объект класса QTcpServer будет слушать один из портов стека протоколов TCP/IP от всех хостов в сети. Прослушивание порта устанавливается методом listen() с указанием специфицированного IP-адреса или диапазона IP-адресов, а также порта прослушивания.

Когда происходит подключение клиента к порту вызывается сигнал newConnection() , который будет поключён к слоту slotNewConnection(), в данном слоте будет инициировано подключение клиента в качестве объекта QTcpSocket на стороне сервера с помощью метода nextPendingConnection(), который возвращает указатель на объект QTcpSocket.

К новому сокету будет подключено два слота. Первый слот slotServerRead() будет подключён к сигналу readyRead от сокета и будет вызываться в том случае, если на сокет пришли данные, которые готовы к чтению. Второй слот slotClientDisconnected() подключён к сигналу disconnected() , который вызывается в том случае, когда клиент отключился от сервера и необходимо закрыть соединение со стороны сервера.

Структура проекта для работы с QTcpServer

Будет создано консольное приложение, следовательно классов вроде MainWindow в приложении использовано не будет.

  • EchoServer.pro - профайл проекта;
  • main.cpp - основной файл исходных кодов;
  • mytcpserver.h - заголовочный файл сервера;
  • mytcpserver.cpp - файл исходных кодов сервера;

EchoServer.pro

В данном файле необходимо добавить Qt модуль для работы с сетью.

QT += network

main.cpp

Всё, что нужно сделать в данном файле, это подключить заголовочный файл сервера и создать экземпляр сервера.

#include <QCoreApplication>
#include "mytcpserver.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    MyTcpServer server;

    return a.exec();
}

mytcpserver.h

Данный класс является обёрткой для работы с QTcpServer и наследован от QObject для применения сигналов и слотов .

#ifndef MYTCPSERVER_H
#define MYTCPSERVER_H

#include <QObject>
#include <QTcpServer>
#include <QTcpSocket>

class MyTcpServer : public QObject
{
    Q_OBJECT
public:
    explicit MyTcpServer(QObject *parent = 0);

public slots:
    void slotNewConnection();
    void slotServerRead();
    void slotClientDisconnected();

private:
    QTcpServer * mTcpServer;
    QTcpSocket * mTcpSocket;
};

#endif // MYTCPSERVER_H

mytcpserver.cpp

#include "mytcpserver.h"
#include <QDebug>
#include <QCoreApplication>

MyTcpServer::MyTcpServer(QObject *parent) : QObject(parent)
{
    mTcpServer = new QTcpServer(this);

    connect(mTcpServer, &QTcpServer::newConnection, this, &MyTcpServer::slotNewConnection);

    if(!mTcpServer->listen(QHostAddress::Any, 6000)){
        qDebug() << "server is not started";
    } else {
        qDebug() << "server is started";
    }
}

void MyTcpServer::slotNewConnection()
{
    mTcpSocket = mTcpServer->nextPendingConnection();

    mTcpSocket->write("Hello, World!!! I am echo server!\r\n");

    connect(mTcpSocket, &QTcpSocket::readyRead, this, &MyTcpServer::slotServerRead);
    connect(mTcpSocket, &QTcpSocket::disconnected, this, &MyTcpServer::slotClientDisconnected);
}

void MyTcpServer::slotServerRead()
{
    while(mTcpSocket->bytesAvailable()>0)
    {
        QByteArray array = mTcpSocket->readAll();

        mTcpSocket->write(array);
    }
}

void MyTcpServer::slotClientDisconnected()
{
    mTcpSocket->close();
}

Работа с Echo Server

После того, как Вы соберёте проект и у Вас запустится консольное приложение, воспользуйтесь любым программным обеспечением, которое поддерживает telnet, например Putty, и подключитесь на настроенный порт. Попробуйте отослать данные сервер, чтобы убедиться, что он Вам их вернёт. В некоторых случаях этого может не произойти или Вы вообще не сможете подключиться, тогда отключите FireWall, часто проблема скрывается именно в нём.

Демонстрация работы приложения с дополнительными комментариями представлена в видеоуроке.

Ссылка на скачивание проекта в zip-архиве: echoserver.zip

Видеоурок

Комментарии

Комментарии

Только авторизованные пользователи могут оставлять комментарии.
Пожалуйста, Авторизуйтесь или Зарегистрируйтесь
15 июня 2018 г. 12:42
Nicky

C++ - Тест 004. Указатели, Массивы и Циклы

  • Результат 100 баллов
  • Очки рейтинга 10
15 июня 2018 г. 12:36
Nicky

C++ - Тест 003. Условия и циклы

  • Результат 57 баллов
  • Очки рейтинга -2
15 июня 2018 г. 12:29
Nicky

C++ - Тест 001. Первая программа и типы данных

  • Результат 46 баллов
  • Очки рейтинга -6
Последние комментарии
18 июня 2018 г. 7:12
EVILEG

PyQt5 - Урок 007. Работаем с QML QtQuick (Сигналы и слоты)

Я вот сейчас банальность скажу, но у меня всё работало. Так что даже и не знаю, надо на код смотреть, что ещё у вас добавлено или отсутствует из библиотек. P/S/ Извините, вы сейчас вс...
18 июня 2018 г. 7:10
EVILEG

Qt/C++ - Урок 042. PopUp уведомление в стиле Gnome с помощью Qt

Недоработки, вряд ли этот зверь вообще является официально поддерживаемым
18 июня 2018 г. 7:01
EVILEG

QML - Урок 016. База данных SQLite и работа с ней в QML Qt

что-то мне сдаётся, что здесь просто пересобрать проект нужно с удалением build каталога
18 июня 2018 г. 7:00
EVILEG

Qt - WinAPI. Как показать запущенное приложение поверх своего приложения

Если зарыться в API системы, то, думаю, что можно, тут тоже использовался WinAPI.
16 июня 2018 г. 15:19
pro100belik

Qt - WinAPI. Как показать запущенное приложение поверх своего приложения

А можно по ID процесса  выводить на передний план окно? myProcess->processId();
Сейчас обсуждают на форуме
19 июня 2018 г. 7:56
EVILEG

как редактировать порядок обхода этементов по нажатию TAB в Qt5 qml

Что-то наподобие такого TextField { Keys.onReturnPressed: nextItemInFocusChain().forceActiveFocus()}
19 июня 2018 г. 6:31
kabanov

Как сохранить фокус в TextField после перезагрузки модели

Rectangle { ListView { id: listView delegate: Item { id: cDelegate Item { Row { ComboBox { ...
18 июня 2018 г. 10:51
alex_lip

Qml and JavaScript

В том то и дело что просто в JS так нельзя Если использовать state - onReleased - не нужен вот так все работает Text { ...
18 июня 2018 г. 7:16
EVILEG

почему не выполняется код после вызова слота?

в рамках какого кода, из вашего вопроса не понятно, к чему вы задали этот вопрос и к чему это относится. Если мне ещё ясно, к какой статье этот вопрос был задан, поскольку я слежу за всем ре...

Рекомендуемые страницы