Evgenii Legotckoi
Evgenii Legotckoi08 грудня 2015 р. 10:20

Qt/C++ - Урок 034. Сервер Echo на основі 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
  • 02 липня 2021 р. 06:36

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

ИВ
  • 02 липня 2021 р. 06: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?

Коментарі

Only authorized users can post comments.
Please, Log in or Sign up
OI
  • Ora Iro
  • 24 грудня 2024 р. 17:38

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

  • Результат:40бали,
  • Рейтинг балів-8
AD

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

  • Результат:50бали,
  • Рейтинг балів-4
m
  • molni99
  • 26 жовтня 2024 р. 11:37

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

  • Результат:80бали,
  • Рейтинг балів4
Останні коментарі
ИМ
Игорь Максимов22 листопада 2024 р. 22:51
Django - Підручник 017. Налаштуйте сторінку входу до Django Добрый вечер Евгений! Я сделал себе авторизацию аналогичную вашей, все работает, кроме возврата к предидущей странице. Редеректит всегда на главную, хотя в логах сервера вижу запросы на правильн…
Evgenii Legotckoi
Evgenii Legotckoi01 листопада 2024 р. 00:37
Django - Урок 064. Як написати розширення для Python Markdown Добрый день. Да, можно. Либо через такие же плагины, либо с постобработкой через python библиотеку Beautiful Soup
A
ALO1ZE19 жовтня 2024 р. 18:19
Читалка файлів fb3 на Qt Creator Подскажите как это запустить? Я не шарю в программировании и кодинге. Скачал и установаил Qt, но куча ошибок выдается и не запустить. А очень надо fb3 переконвертировать в html
ИМ
Игорь Максимов05 жовтня 2024 р. 17:51
Django - Урок 064. Як написати розширення для Python Markdown Приветствую Евгений! У меня вопрос. Можно ли вставлять свои классы в разметку редактора markdown? Допустим имея стандартную разметку: <ul> <li></li> <li></l…
d
dblas505 липня 2024 р. 21:02
QML - Урок 016. База даних SQLite та робота з нею в QML Qt Здравствуйте, возникает такая проблема (я новичок): ApplicationWindow неизвестный элемент. (М300) для TextField и Button аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
n
nkly03 січня 2025 р. 13:52
Нужно запретить перемещение только некоторых итемов, остальные перемещать можно. Вопрос решен. Узнать QModelIndex элемента на который мы перетаскиваем другой элемент, можно с помощью функции indexAt(event->position().toPoint()) представления QTreeViev вызываемой в переопр…
AW
Ayden Watkins02 січня 2025 р. 11:09
Why Paying for a Research Paper Can Be a Smart Choice Writing a research paper can be a daunting task, especially when faced with tight deadlines, complex topics, or a lack of resources. For many students, paying for a research paper is a practical…
p
pimacontrols8531 грудня 2024 р. 20:39
Finding the Right Rittal Small Enclosure for Your Needs Rittal is a leading manufacturer of enclosures for industrial and IT applications. Their small enclosures offer a compact and reliable solution for a wide range of needs, from housing electronic…
Donald Randolph
Donald Randolph30 грудня 2024 р. 13:59
Personal Injury lawyer Santa Monica As an experienced Santa Monica personal injury lawyer, Donald C. Randolph has recovered over $100 Million in verdicts and settlements for our clients. In severe injury cases, this compensation i…
Nirvana Yoga School
Nirvana Yoga School30 грудня 2024 р. 16:13
OAuth2.0 через VK, получение email Nirvana Yoga School is one of the most trusted and reputed traditional Rishikesh yoga courses , India certified by Yoga Alliance, USA. We aim to spread traditional yoga teachings so t…

Слідкуйте за нами в соціальних мережах