Реализация клиента и сервера
parent
c58fa4e814
commit
c637706c22
21
README.md
21
README.md
|
@ -1,3 +1,22 @@
|
|||
# TcpSocket_Client_Server_Example
|
||||
|
||||
Пример реализации клиента и сервера для обмена данными по TCP/IP
|
||||
Пример реализации клиента и сервера для обмена данными по TCP/IP.
|
||||
|
||||
## Тестовое задание
|
||||
|
||||
Реализовать на Qt сервер, который будет принимать входящие соединения по TCP на определенном порту.
|
||||
Реализовать следующие функции:
|
||||
- открытие и закрытие входящего порта сервера;
|
||||
- чтение входящего пакета от клиента в виде массива байт;
|
||||
- обработка полученного массива по алгоритму (см. ниже);
|
||||
- отправка нового массива обратно клиенту.
|
||||
|
||||
Алгоритм обработки входящего массива:
|
||||
- если значение очередного байта 0x00 или 0xFF, заменить на 0xAA;
|
||||
- иначе на четных индексах увеличить значение на 1;
|
||||
- на нечетных позициях уменьшить значение на 1.
|
||||
|
||||
Приложение может быть реализовано в виде ПО с графическим интерфейсом, либо в виде консольного приложения.
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -29,11 +29,21 @@
|
|||
#include <QtCore/QDebug>
|
||||
#include <QtCore/QDir>
|
||||
#include <QtCore/QStringList>
|
||||
#include <QtCore/QDateTime>
|
||||
|
||||
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
|
||||
# include <QtCore/QTextCodec>
|
||||
#endif
|
||||
|
||||
//==============================================================================
|
||||
|
||||
const char * clDefault[2] { "#111416", "#fdfdfd" };
|
||||
const char * clLogDate[2] { "#929292", "#333333" };
|
||||
const char * clLogInf[2] { "#ffffff", "#000000" };
|
||||
const char * clLogWrn[2] { "#ff9c54", "#8d3c00" };
|
||||
const char * clLogErr[2] { "#ff4040", "#a50000" };
|
||||
const char * clLogIn[2] { "#55d864", "#003706" };
|
||||
|
||||
//==============================================================================
|
||||
void Application::initialize()
|
||||
{
|
||||
|
@ -104,3 +114,57 @@ void Application::installTranslations(const QString &lng)
|
|||
}
|
||||
}
|
||||
//==============================================================================
|
||||
void Application::initializeLog(QTextEdit *textEdit)
|
||||
{
|
||||
if (!textEdit)
|
||||
return;
|
||||
|
||||
textEdit->setStyleSheet(
|
||||
QString(
|
||||
"QTextEdit { "
|
||||
"color: %1; "
|
||||
"background-color: %2; "
|
||||
"font-family: Courier New, Cascadia Mono, Lucida Console, Monospace; "
|
||||
"font-size: 10pt; "
|
||||
"}"
|
||||
)
|
||||
.arg( clDefault[ 1 ], clDefault[ 0 ] )
|
||||
);
|
||||
textEdit->document()->setMaximumBlockCount(10000);
|
||||
}
|
||||
//==============================================================================
|
||||
void Application::addToLog(QTextEdit *textEdit, const QString &text, LogType logType)
|
||||
{
|
||||
if (!textEdit)
|
||||
return;
|
||||
|
||||
const QString line {"<font color=\"%1\">[%2]</font> <font color=\"%3\">%4</font>"};
|
||||
|
||||
QString cl = QString(clLogInf[ 0 ]);
|
||||
|
||||
switch (logType) {
|
||||
case LogTypeError:
|
||||
cl = QString(clLogErr[ 0 ]);
|
||||
break;
|
||||
case LogTypeWarning:
|
||||
cl = QString(clLogWrn[ 0 ]);
|
||||
break;
|
||||
case LogTypeData:
|
||||
cl = QString(clLogIn[ 0 ]);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
textEdit->append(
|
||||
line.arg(
|
||||
QString(clLogDate[ 0 ]),
|
||||
QDateTime::currentDateTime().toString("HH:mm:ss"),
|
||||
cl,
|
||||
text.toHtmlEscaped()
|
||||
)
|
||||
);
|
||||
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
}
|
||||
//==============================================================================
|
||||
|
|
|
@ -27,17 +27,26 @@
|
|||
#define APP_CONFIG_H
|
||||
|
||||
#include <QtCore/QString>
|
||||
#include <QtWidgets/QTextEdit>
|
||||
|
||||
//==============================================================================
|
||||
|
||||
class Application
|
||||
{
|
||||
Q_DISABLE_COPY(Application)
|
||||
|
||||
public:
|
||||
enum LogType {
|
||||
LogTypeInfo,
|
||||
LogTypeData,
|
||||
LogTypeError,
|
||||
LogTypeWarning
|
||||
};
|
||||
|
||||
static void initialize();
|
||||
static QString applicationRootPath();
|
||||
static void installTranslations(const QString &lng = "ru");
|
||||
static void initializeLog(QTextEdit *textEdit);
|
||||
static void addToLog(QTextEdit *textEdit, const QString &text, LogType logType = LogTypeInfo);
|
||||
|
||||
private:
|
||||
Application() = delete;
|
||||
|
|
|
@ -24,7 +24,14 @@
|
|||
****************************************************************************/
|
||||
#include "main_window.h"
|
||||
#include "./ui_main_window.h"
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QRegularExpressionValidator>
|
||||
#include <QtNetwork/QHostAddress>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
#include "application_config.h"
|
||||
|
||||
namespace client { //===========================================================
|
||||
|
||||
|
@ -34,13 +41,244 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle( QApplication::applicationName() );
|
||||
|
||||
initialize();
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
socket.disconnectFromHost();
|
||||
delete ui;
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::initialize()
|
||||
{
|
||||
setWindowTitle( QApplication::applicationName() );
|
||||
Application::initializeLog(ui->textEditLog);
|
||||
|
||||
connect(ui->pushButtonConnect, &QPushButton::clicked, this, &MainWindow::btnConnect);
|
||||
connect(ui->pushButtonSend, &QPushButton::clicked, this, &MainWindow::btnSend);
|
||||
connect(&socket, &QTcpSocket::connected, this, &MainWindow::socketConnected);
|
||||
connect(&socket, &QTcpSocket::disconnected, this, &MainWindow::socketDisconnected);
|
||||
|
||||
QString ipRange {"(?:[0-1]?[0-9]?[0-9]|2[0-4][0-9]|25[0-5])"};
|
||||
QRegularExpression ipRegex ("^" + ipRange
|
||||
+ "\\." + ipRange
|
||||
+ "\\." + ipRange
|
||||
+ "\\." + ipRange + "$");
|
||||
|
||||
ui->lineEditIp->setValidator( new QRegularExpressionValidator(ipRegex, this) );
|
||||
ui->lineEditIp->setText("127.0.0.1");
|
||||
|
||||
QRegularExpression hexRegex("([a-fA-F0-9]{2})([\\s][a-fA-F0-9]{2})*[\\s]?");
|
||||
ui->lineEditData->setValidator( new QRegularExpressionValidator(hexRegex, this) );
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::updateControls()
|
||||
{
|
||||
bool connect = isConnected();
|
||||
|
||||
ui->pushButtonSend->setEnabled(connect);
|
||||
ui->lineEditIp->setEnabled(!connect);
|
||||
ui->spinBoxPort->setEnabled(!connect);
|
||||
|
||||
ui->pushButtonConnect->setText(connect ? tr("Закрыть") : tr("Открыть"));
|
||||
}
|
||||
//==============================================================================
|
||||
bool MainWindow::isConnected() const
|
||||
{
|
||||
return socket.state() == QTcpSocket::SocketState::ConnectedState;
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::btnConnect()
|
||||
{
|
||||
ui->pushButtonConnect->setEnabled(false);
|
||||
ui->pushButtonSend->setEnabled(false);
|
||||
ui->lineEditData->setEnabled(false);
|
||||
ui->lineEditIp->setEnabled(false);
|
||||
ui->spinBoxPort->setEnabled(false);
|
||||
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
if (isConnected()) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Закрытие соединения с сервером..."));
|
||||
socket.disconnectFromHost();
|
||||
|
||||
if (socket.state() != QAbstractSocket::UnconnectedState) {
|
||||
|
||||
if (!socket.waitForDisconnected(timeout)) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Не удалось закрыть соединение: %1")
|
||||
.arg(socket.errorString()),
|
||||
Application::LogTypeError);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Открытие соединения с сервером..."));
|
||||
socket.connectToHost(
|
||||
QHostAddress(ui->lineEditIp->text()),
|
||||
static_cast<quint16>(ui->spinBoxPort->value())
|
||||
);
|
||||
|
||||
if (socket.state() != QTcpSocket::SocketState::ConnectedState) {
|
||||
|
||||
if (!socket.waitForConnected(timeout)) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Не удалось открыть соединение: %1")
|
||||
.arg(socket.errorString()),
|
||||
Application::LogTypeError);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ui->pushButtonConnect->setEnabled(true);
|
||||
ui->lineEditData->setEnabled(true);
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::btnSend()
|
||||
{
|
||||
if (!isConnected())
|
||||
return;
|
||||
|
||||
QStringList list = ui->lineEditData->text().split(' ', Qt::SkipEmptyParts);
|
||||
QByteArray sendData;
|
||||
|
||||
for (const QString &str: std::as_const(list) ) {
|
||||
|
||||
sendData.append( static_cast<char>( str.toInt(nullptr, 16) ) );
|
||||
}
|
||||
|
||||
if (sendData.isEmpty()) return;
|
||||
|
||||
ui->pushButtonSend->setEnabled(false);
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Отправка массива %1 байт").arg(sendData.size()));
|
||||
|
||||
qsizetype sendCount {0};
|
||||
QElapsedTimer timer;
|
||||
|
||||
timer.start();
|
||||
|
||||
while ((sendCount < sendData.size()) && (timer.elapsed() < timeout)) {
|
||||
|
||||
qsizetype count = socket.write(sendData.mid(
|
||||
static_cast<int>(sendCount)
|
||||
));
|
||||
|
||||
if (count < 0) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Ошибка отправки данных"), Application::LogTypeError );
|
||||
}
|
||||
else if (count > 0) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Отправка данных: %1 (%2 байт)")
|
||||
.arg(
|
||||
QString(
|
||||
sendData.mid(
|
||||
static_cast<int>(sendCount),
|
||||
static_cast<int>(count) )
|
||||
.toHex(' '))
|
||||
).arg(count),
|
||||
Application::LogTypeData
|
||||
);
|
||||
sendCount += count;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendCount < sendData.size()) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Таймаут отправки данных. Всего отправлено %1 байт из %2")
|
||||
.arg(sendCount).arg(sendData.size()),
|
||||
Application::LogTypeError );
|
||||
}
|
||||
|
||||
if (sendCount == 0) {
|
||||
|
||||
updateControls();
|
||||
return;
|
||||
}
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Приём массива %1 байт").arg(sendData.size()));
|
||||
|
||||
if (!socket.waitForReadyRead(timeout)) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Таймаут ожидания приёма данных"), Application::LogTypeError );
|
||||
updateControls();
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray readData;
|
||||
timer.restart();
|
||||
|
||||
while ((readData.size() < sendData.size()) && (timer.elapsed() < timeout)) {
|
||||
|
||||
QByteArray buf = socket.read( sendData.size() - readData.size() );
|
||||
|
||||
if (!buf.isEmpty()) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Приём данных: %1 (%2 байт)")
|
||||
.arg(
|
||||
QString(buf.toHex(' '))
|
||||
).arg(buf.size()),
|
||||
Application::LogTypeData
|
||||
);
|
||||
readData.append(buf);
|
||||
}
|
||||
}
|
||||
|
||||
if (readData.size() < sendData.size()) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Таймаут приёма данных. Всего принято %1 байт из %2")
|
||||
.arg(readData.size()).arg(sendData.size()),
|
||||
Application::LogTypeError );
|
||||
}
|
||||
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::socketConnected()
|
||||
{
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Соединение открыто. Ip: %1, Порт: %2")
|
||||
.arg(ui->lineEditIp->text()).arg(ui->spinBoxPort->value()),
|
||||
Application::LogTypeWarning);
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::socketDisconnected()
|
||||
{
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Соединение закрыто"), Application::LogTypeWarning);
|
||||
ui->textEditLog->append("");
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
|
||||
} // namespace //===============================================================
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define CLIENT_MAINWINDOW_H
|
||||
//==============================================================================
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
|
||||
//==============================================================================
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -47,8 +48,20 @@ public:
|
|||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
const int timeout {5000};
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
QTcpSocket socket;
|
||||
|
||||
void initialize();
|
||||
void updateControls();
|
||||
bool isConnected() const;
|
||||
|
||||
private slots:
|
||||
void btnConnect();
|
||||
void btnSend();
|
||||
void socketConnected();
|
||||
void socketDisconnected();
|
||||
};
|
||||
|
||||
} // namespace //===============================================================
|
||||
|
|
|
@ -24,7 +24,14 @@
|
|||
****************************************************************************/
|
||||
#include "main_window.h"
|
||||
#include "./ui_main_window.h"
|
||||
|
||||
#include <QtWidgets/QApplication>
|
||||
#include <QtGui/QRegularExpressionValidator>
|
||||
#include <QtNetwork/QHostAddress>
|
||||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QElapsedTimer>
|
||||
|
||||
#include "application_config.h"
|
||||
|
||||
namespace server { //===========================================================
|
||||
|
||||
|
@ -34,14 +41,257 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
, ui(new Ui::MainWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setWindowTitle( QApplication::applicationName() );
|
||||
|
||||
initialize();
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
disconnectClients();
|
||||
server.close();
|
||||
|
||||
delete ui;
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::initialize()
|
||||
{
|
||||
setWindowTitle( QApplication::applicationName() );
|
||||
Application::initializeLog(ui->textEditLog);
|
||||
|
||||
connect(ui->pushButtonConnect, &QPushButton::clicked, this, &MainWindow::btnConnect);
|
||||
connect(&server, &QTcpServer::newConnection, this, &MainWindow::newConnection);
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::updateControls()
|
||||
{
|
||||
bool connect {server.isListening()};
|
||||
|
||||
ui->spinBoxPort->setEnabled(!connect);
|
||||
ui->pushButtonConnect->setText(connect ? tr("Закрыть") : tr("Открыть"));
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::disconnectClients()
|
||||
{
|
||||
while (!clients.isEmpty()) {
|
||||
|
||||
QTcpSocket *socket = clients.takeLast();
|
||||
|
||||
if (socket) {
|
||||
|
||||
socket->close();
|
||||
|
||||
if (socket->state() != QAbstractSocket::UnconnectedState)
|
||||
socket->waitForDisconnected(2000);
|
||||
}
|
||||
}
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::btnConnect()
|
||||
{
|
||||
ui->pushButtonConnect->setEnabled(false);
|
||||
ui->spinBoxPort->setEnabled(false);
|
||||
|
||||
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents);
|
||||
|
||||
if (server.isListening()) {
|
||||
|
||||
disconnectClients();
|
||||
server.close();
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Сервер закрыт"),
|
||||
Application::LogTypeWarning);
|
||||
|
||||
ui->textEditLog->append("");
|
||||
}
|
||||
else {
|
||||
|
||||
if (server.listen(
|
||||
QHostAddress::Any,
|
||||
static_cast<quint16>(ui->spinBoxPort->value())
|
||||
)
|
||||
) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Сервер открыт для входящих подключений на порту %1")
|
||||
.arg(ui->spinBoxPort->value()),
|
||||
Application::LogTypeWarning);
|
||||
}
|
||||
else {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Не удалось открыть сервер (%1)").arg(server.errorString()),
|
||||
Application::LogTypeError);
|
||||
}
|
||||
}
|
||||
|
||||
ui->pushButtonConnect->setEnabled(true);
|
||||
updateControls();
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::newConnection()
|
||||
{
|
||||
QTcpSocket* socket = server.nextPendingConnection();
|
||||
|
||||
if (!socket)
|
||||
return;
|
||||
|
||||
clients.append(socket);
|
||||
|
||||
connect(socket, &QTcpSocket::readyRead, this, &MainWindow::clientRead);
|
||||
connect(socket, &QTcpSocket::disconnected, this, &MainWindow::clientDisconnect);
|
||||
|
||||
QHostAddress clientAddress = socket->peerAddress();
|
||||
quint16 clientPort = socket->peerPort();
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Входящее подключение. Адрес клиента: %1; Порт клиента: %2")
|
||||
.arg(clientAddress.toString()).arg(clientPort),
|
||||
Application::LogTypeWarning);
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::clientRead()
|
||||
{
|
||||
QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender());
|
||||
|
||||
if (!socket)
|
||||
return;
|
||||
|
||||
QHostAddress clientAddress = socket->peerAddress();
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Чтение входящих данных с %1").arg(clientAddress.toString()));
|
||||
|
||||
QByteArray readData;
|
||||
QElapsedTimer timer;
|
||||
|
||||
timer.start();
|
||||
|
||||
while (readData.isEmpty() && (timer.elapsed() < timeout)) {
|
||||
|
||||
readData = socket->readAll();
|
||||
}
|
||||
|
||||
if (readData.isEmpty()) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Таймаут ожидания данных с %1").arg(clientAddress.toString()),
|
||||
Application::LogTypeError);
|
||||
return;
|
||||
}
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Принятые данные c %1: %2 (%3 байт)")
|
||||
.arg(clientAddress.toString(), QString(readData.toHex(' ')))
|
||||
.arg(readData.size()),
|
||||
Application::LogTypeData);
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Обработка массива %1 байт").arg(readData.size()));
|
||||
|
||||
QByteArray sendData;
|
||||
|
||||
// Преобразование данных в выходной массив:
|
||||
// если значение 0x00 или 0xFF, заменить на 0xAA
|
||||
// иначе на четных индексах увеличить значение на 1
|
||||
// на нечетных уменьшить значение на 1
|
||||
|
||||
for (auto i = 0; i < readData.size(); ++i) {
|
||||
|
||||
quint8 byte = static_cast<quint8>( readData.at(i) );
|
||||
|
||||
if ((byte == 0) || (byte == 0xFF))
|
||||
byte = 0xAA;
|
||||
else if ((i % 2) == 0)
|
||||
++byte;
|
||||
else
|
||||
--byte;
|
||||
|
||||
sendData.append( static_cast<char>(byte) );
|
||||
}
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Данные после обработки: %1")
|
||||
.arg(
|
||||
QString(sendData.toHex(' '))
|
||||
),
|
||||
Application::LogTypeData
|
||||
);
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Отправка данных клиенту %1").arg(clientAddress.toString()));
|
||||
|
||||
qsizetype sendCount {0};
|
||||
timer.restart();
|
||||
|
||||
while ((sendCount < sendData.size()) && (timer.elapsed() < timeout)) {
|
||||
|
||||
qsizetype count = socket->write(sendData.mid(
|
||||
static_cast<int>(sendCount)
|
||||
));
|
||||
|
||||
if (count < 0) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Ошибка отправки данных на %1")
|
||||
.arg(clientAddress.toString()),
|
||||
Application::LogTypeError );
|
||||
}
|
||||
else if (count > 0) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Отправка данных на %1: %2 (%3 байт)")
|
||||
.arg(clientAddress.toString(),
|
||||
QString(sendData.mid(
|
||||
static_cast<int>(sendCount),
|
||||
static_cast<int>(count)
|
||||
).toHex(' ')))
|
||||
.arg(count),
|
||||
Application::LogTypeData
|
||||
);
|
||||
sendCount += count;
|
||||
}
|
||||
}
|
||||
|
||||
if (sendCount < sendData.size()) {
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog, tr("Таймаут отправки данных на %1. Всего отправлено %2 байт из %3")
|
||||
.arg(clientAddress.toString()).arg(sendCount).arg(sendData.size()),
|
||||
Application::LogTypeError );
|
||||
}
|
||||
}
|
||||
//==============================================================================
|
||||
void MainWindow::clientDisconnect()
|
||||
{
|
||||
QString clientAddressStr;
|
||||
|
||||
if (sender()) {
|
||||
|
||||
QTcpSocket* socket = qobject_cast<QTcpSocket*>(sender());
|
||||
|
||||
if (socket) {
|
||||
|
||||
QHostAddress clientAddress = socket->peerAddress();
|
||||
clientAddressStr = clientAddress.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Application::addToLog(
|
||||
ui->textEditLog,
|
||||
tr("Закрытие входящего подключения %1").arg(clientAddressStr),
|
||||
Application::LogTypeWarning);
|
||||
}
|
||||
//==============================================================================
|
||||
|
||||
} // mamespace //===============================================================
|
||||
|
||||
|
|
|
@ -25,8 +25,12 @@
|
|||
#pragma once
|
||||
#ifndef SERVER_MAINWINDOW_H
|
||||
#define SERVER_MAINWINDOW_H
|
||||
//==============================================================================
|
||||
|
||||
#include <QtWidgets/QMainWindow>
|
||||
#include <QtNetwork/QTcpServer>
|
||||
#include <QtNetwork/QTcpSocket>
|
||||
#include <QtCore/QMap>
|
||||
#include <QtCore/QList>
|
||||
|
||||
//==============================================================================
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
@ -47,8 +51,21 @@ public:
|
|||
~MainWindow();
|
||||
|
||||
private:
|
||||
Ui::MainWindow *ui;
|
||||
const qint64 timeout {5000};
|
||||
|
||||
Ui::MainWindow *ui;
|
||||
QTcpServer server;
|
||||
QList<QTcpSocket*> clients;
|
||||
|
||||
void initialize();
|
||||
void updateControls();
|
||||
void disconnectClients();
|
||||
|
||||
private slots:
|
||||
void btnConnect();
|
||||
void newConnection();
|
||||
void clientRead();
|
||||
void clientDisconnect();
|
||||
};
|
||||
|
||||
} // mamespace //===============================================================
|
||||
|
|
Loading…
Reference in New Issue