Evgenii Legotckoi
Evgenii Legotckoi8 декабря 2015 г. 10:20

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

Для работы со стеком 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

Видеоурок

Рекомендуем хостинг TIMEWEB
Рекомендуем хостинг TIMEWEB
Стабильный хостинг, на котором располагается социальная сеть EVILEG. Для проектов на Django рекомендуем VDS хостинг.

Вам это нравится? Поделитесь в социальных сетях!

ИВ
  • 15 марта 2021 г. 14:46
  • (ред.)

Добрый день, разрешите вопрос:
во всех примерах работы с QTcpServer его всегда создают в main.cpp, нет ли возможности корректно сохдать его в MainWindow.cpp ?
Просто если перенести код в MainWindow.cpp

#include "myserver.h"

MainWindow::MainWindow( QWidget *parent): QMainWindow(parent) , ui(new Ui::MainWindow)
{
    myserver Server;
    Server.startServer();
    ui->setupUi(this);

то возникает ошибка на клиенте QNativeSocketEngine::write() was not called in QAbstractSocket::ConnectedState

Evgenii Legotckoi
  • 2 июля 2021 г. 6:36

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

ИВ
  • 2 июля 2021 г. 6:51

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

e
  • 16 августа 2021 г. 12:43

Hi, great post.

If I were to reimplement QTcpServer for the purposes of SSL, shouldn't incomingConnection(int socket) just be automatically called after a connection occurs?

Комментарии

Только авторизованные пользователи могут публиковать комментарии.
Пожалуйста, авторизуйтесь или зарегистрируйтесь
d
  • dsfs
  • 26 апреля 2024 г. 14:56

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

  • Результат:80баллов,
  • Очки рейтинга4
d
  • dsfs
  • 26 апреля 2024 г. 14:45

C++ - Тест 002. Константы

  • Результат:50баллов,
  • Очки рейтинга-4
d
  • dsfs
  • 26 апреля 2024 г. 14:35

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

  • Результат:73баллов,
  • Очки рейтинга1
Последние комментарии
k
kmssr9 февраля 2024 г. 5:43
Qt Linux - Урок 001. Автозапуск Qt приложения под Linux как сделать автозапуск для флэтпака, который не даёт создавать файлы в ~/.config - вот это вопрос ))
АК
Анатолий Кононенко5 февраля 2024 г. 12:50
Qt WinAPI - Урок 007. Работаем с ICMP Ping в Qt Без строки #include <QRegularExpressionValidator> в заголовочном файле не работает валидатор.
EVA
EVA25 декабря 2023 г. 21:30
Boost - статическая линковка в CMake проекте под Windows Ошибка LNK1104 часто возникает, когда компоновщик не может найти или открыть файл библиотеки. В вашем случае, это файл libboost_locale-vc142-mt-gd-x64-1_74.lib из библиотеки Boost для C+…
J
JonnyJo25 декабря 2023 г. 19:38
Boost - статическая линковка в CMake проекте под Windows Сделал всё по-как у вас, но выдаёт ошибку [build] LINK : fatal error LNK1104: не удается открыть файл "libboost_locale-vc142-mt-gd-x64-1_74.lib" Хоть убей, не могу понять в чём дел…
G
Gvozdik19 декабря 2023 г. 8:01
Qt/C++ - Урок 056. Подключение библиотеки Boost в Qt для компиляторов MinGW и MSVC Для решения твой проблемы добавь в файл .pro строчку "LIBS += -lws2_32" она решит проблему , лично мне помогло.
Сейчас обсуждают на форуме
G
Gar22 апреля 2024 г. 15:46
Clipboard Как скопировать окно целиком в clipb?
DA
Dr Gangil Academics20 апреля 2024 г. 17:45
Unlock Your Aesthetic Potential: Explore MSC in Facial Aesthetics and Cosmetology in India Embark on a transformative journey with an msc in facial aesthetics and cosmetology in india . Delve into the intricate world of beauty and rejuvenation, guided by expert faculty and …
a
a_vlasov14 апреля 2024 г. 16:41
Мобильное приложение на C++Qt и бэкенд к нему на Django Rest Framework Евгений, добрый день! Такой вопрос. Верно ли следующее утверждение: Любое Android-приложение, написанное на Java/Kotlin чисто теоретически (пусть и с большими трудностями) можно написать и на C+…
Павел Дорофеев
Павел Дорофеев14 апреля 2024 г. 12:35
QTableWidget с 2 заголовками Вот тут есть кастомный QTableView с многорядностью проект поддерживается, обращайтесь
f
fastrex4 апреля 2024 г. 14:47
Вернуть старое поведение QComboBox, не менять индекс при resetModel Добрый день! У нас много проектов в которых используется QComboBox, в версии 5.5.1, когда модель испускает сигнал resetModel, currentIndex не менялся. В версии 5.15 при resetModel происходит try…

Следите за нами в социальных сетях