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
AD

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

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

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

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

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

  • Результат:20бали,
  • Рейтинг балів-10
Останні коментарі
ИМ
Игорь Максимов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 аналогично. Могу предположить, что из-за более новой верси…
Тепер обговоріть на форумі
Evgenii Legotckoi
Evgenii Legotckoi25 червня 2024 р. 01:11
добавить qlineseries в функции Я тут. Работы оень много. Отправил его в бан.
t
tonypeachey115 листопада 2024 р. 17:04
google domain [url=https://google.com/]domain[/url] domain [http://www.example.com link title]
NSProject
NSProject04 червня 2022 р. 13:49
Всё ещё разбираюсь с кешем. В следствии прочтения данной статьи. Я принял для себя решение сделать кеширование свойств менеджера модели LikeDislike. И так как установка evileg_core для меня не была возможна, ибо он писался…
9
9Anonim25 жовтня 2024 р. 19:10
Машина тьюринга // Начальное состояние 0 0, ,<,1 // Переход в состояние 1 при пустом символе 0,0,>,0 // Остаемся в состоянии 0, двигаясь вправо при встрече 0 0,1,>…

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