diff --git a/Lesson_6/Task_1/Client/.gitignore b/Lesson_6/Task_1/Client/.gitignore new file mode 100644 index 0000000..4a0b530 --- /dev/null +++ b/Lesson_6/Task_1/Client/.gitignore @@ -0,0 +1,74 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* +CMakeLists.txt.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/Lesson_6/Task_1/Client/Client.pro b/Lesson_6/Task_1/Client/Client.pro new file mode 100644 index 0000000..40cb0ea --- /dev/null +++ b/Lesson_6/Task_1/Client/Client.pro @@ -0,0 +1,24 @@ +QT += core gui network + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +CONFIG += c++17 + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + client.cpp + +HEADERS += \ + client.h + +FORMS += \ + client.ui + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target diff --git a/Lesson_6/Task_1/Client/client.cpp b/Lesson_6/Task_1/Client/client.cpp new file mode 100644 index 0000000..0cf7f44 --- /dev/null +++ b/Lesson_6/Task_1/Client/client.cpp @@ -0,0 +1,82 @@ +#include "client.h" +#include "ui_client.h" + +Client::Client(QWidget *parent) + : QMainWindow(parent) + , ui(new Ui::Client) +{ + ui->setupUi(this); + + connect (ui->b_connect, &QPushButton::clicked, this, &Client::connectPressed); + connect (ui->b_selectFile, &QPushButton::clicked, this, &Client::selectFile); + connect (ui->b_send, &QPushButton::clicked, this, &Client::sendFile); + connect (m_socket, &QTcpSocket::connected, this, &Client::connectionEstablished); +} + +Client::~Client() +{ + delete ui; +} + +void Client::sendFile() +{ + ui->l_status->setText("Connected"); + + QFile file(m_fileName); + QFileInfo fi(m_fileName); + + if (file.open(QIODevice::ReadOnly)) { + m_socket->write((fi.fileName() + '\n').toLocal8Bit()); + + QTextStream in(&file); + + while (!in.atEnd()) + m_socket->write((in.readLine() + '\n').toLocal8Bit()); + } + + ui->l_status->setText("File sent"); + ui->b_send->setEnabled(false); + +} + +void Client::connectPressed() +{ + if (m_socket->isOpen()) { + m_socket->close(); + ui->l_status->setText("Not connected"); + ui->b_connect->setText("Connect"); + ui->b_send->setEnabled(false); + return; + } + QString address = ui->e_address->text(); + int port = ui->sb_port->value(); + + ui->b_connect->setText("Disconnect"); + ui->l_status->setText("Connecting"); + + m_socket->connectToHost(QHostAddress(address), port); +} + +void Client::connectionEstablished() +{ + ui->l_status->setText("Connected"); + checkSendingAllowed(); +} + +void Client::checkSendingAllowed() +{ + if (!m_fileName.isEmpty() && m_socket->isOpen()) + ui->b_send->setEnabled(true); +} + +void Client::selectFile() +{ + m_fileName = QFileDialog::getOpenFileName(this, "Select file", "", "All Files (*)"); + + if (m_fileName.isEmpty()) + return; + + checkSendingAllowed(); +} + + diff --git a/Lesson_6/Task_1/Client/client.h b/Lesson_6/Task_1/Client/client.h new file mode 100644 index 0000000..0fea644 --- /dev/null +++ b/Lesson_6/Task_1/Client/client.h @@ -0,0 +1,37 @@ +#ifndef CLIENT_H +#define CLIENT_H + +#include +#include +#include +#include + +QT_BEGIN_NAMESPACE +namespace Ui { +class Client; +} +QT_END_NAMESPACE + +class Client : public QMainWindow +{ + Q_OBJECT + +public: + Client(QWidget *parent = nullptr); + ~Client(); + +private slots: + void sendFile(); + void connectPressed(); + void connectionEstablished(); + void checkSendingAllowed(); + void selectFile(); + +private: + Ui::Client *ui; + QTcpSocket *m_socket = new QTcpSocket(); + QDataStream m_block; + QFile m_file; + QString m_fileName; +}; +#endif // CLIENT_H diff --git a/Lesson_6/Task_1/Client/client.ui b/Lesson_6/Task_1/Client/client.ui new file mode 100644 index 0000000..47b06c5 --- /dev/null +++ b/Lesson_6/Task_1/Client/client.ui @@ -0,0 +1,111 @@ + + + Client + + + + 0 + 0 + 178 + 231 + + + + Client + + + + + + + + + Address: + + + + + + + + + + + + + + Port: + + + + + + + 1 + + + 65535 + + + + + + + + + Connect + + + + + + + Select file + + + + + + + false + + + Send + + + + + + + + + Status: + + + + + + + Not connected + + + + + + + + + + + 0 + 0 + 178 + 25 + + + + + + + + diff --git a/Lesson_6/Task_1/Client/main.cpp b/Lesson_6/Task_1/Client/main.cpp new file mode 100644 index 0000000..4669bf8 --- /dev/null +++ b/Lesson_6/Task_1/Client/main.cpp @@ -0,0 +1,11 @@ +#include "client.h" + +#include + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + Client w; + w.show(); + return a.exec(); +} diff --git a/Lesson_6/Task_1/Server/.gitignore b/Lesson_6/Task_1/Server/.gitignore new file mode 100644 index 0000000..4a0b530 --- /dev/null +++ b/Lesson_6/Task_1/Server/.gitignore @@ -0,0 +1,74 @@ +# This file is used to ignore files which are generated +# ---------------------------------------------------------------------------- + +*~ +*.autosave +*.a +*.core +*.moc +*.o +*.obj +*.orig +*.rej +*.so +*.so.* +*_pch.h.cpp +*_resource.rc +*.qm +.#* +*.*# +core +!core/ +tags +.DS_Store +.directory +*.debug +Makefile* +*.prl +*.app +moc_*.cpp +ui_*.h +qrc_*.cpp +Thumbs.db +*.res +*.rc +/.qmake.cache +/.qmake.stash + +# qtcreator generated files +*.pro.user* +CMakeLists.txt.user* + +# xemacs temporary files +*.flc + +# Vim temporary files +.*.swp + +# Visual Studio generated files +*.ib_pdb_index +*.idb +*.ilk +*.pdb +*.sln +*.suo +*.vcproj +*vcproj.*.*.user +*.ncb +*.sdf +*.opensdf +*.vcxproj +*vcxproj.* + +# MinGW generated files +*.Debug +*.Release + +# Python byte code +*.pyc + +# Binaries +# -------- +*.dll +*.exe + diff --git a/Lesson_6/Task_1/Server/Server.pro b/Lesson_6/Task_1/Server/Server.pro new file mode 100644 index 0000000..b8833af --- /dev/null +++ b/Lesson_6/Task_1/Server/Server.pro @@ -0,0 +1,19 @@ +QT = core network + +CONFIG += c++17 cmdline + +# You can make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + server.cpp + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +HEADERS += \ + server.h diff --git a/Lesson_6/Task_1/Server/main.cpp b/Lesson_6/Task_1/Server/main.cpp new file mode 100644 index 0000000..8bd2855 --- /dev/null +++ b/Lesson_6/Task_1/Server/main.cpp @@ -0,0 +1,10 @@ +#include +#include + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + Server server; + server.start("0.0.0.0", 8081); + return a.exec(); +} diff --git a/Lesson_6/Task_1/Server/server.cpp b/Lesson_6/Task_1/Server/server.cpp new file mode 100644 index 0000000..b94905c --- /dev/null +++ b/Lesson_6/Task_1/Server/server.cpp @@ -0,0 +1,66 @@ +#include "server.h" + +Server::Server(QObject *parent) + : QObject{parent} +{ + m_server = new QTcpServer(); + + connect (m_server, &QTcpServer::newConnection, this, &Server::newClient); +} + +Server::~Server() +{ + if (m_server->isListening()) { + qDebug() << "Closing server..."; + m_server->close(); + } + delete m_server; +} + +void Server::start(QString host, int port) +{ + bool ok = m_server->listen(QHostAddress(host), port); + if (ok) { + qDebug() << "We are online!"; + } else { + qDebug() << "Error creating connection: " << m_server->errorString(); + } +} + +void Server::newClient() +{ + QTcpSocket *client = m_server->nextPendingConnection(); + qDebug() << "Client " << client->localAddress().toString(); + + connect (client, &QTcpSocket::disconnected, this, &Server::leftClient); + connect (client, &QTcpSocket::readyRead, this, &Server::messageFromClient); + + m_clients.append(client); +} + +void Server::leftClient() +{ + QTcpSocket *socket = (QTcpSocket *)sender(); + + qDebug() << "Client " << socket->localAddress().toString() << " has been left"; + m_clients.removeOne(socket); +} + +void Server::messageFromClient() +{ + QTcpSocket *socket = (QTcpSocket *)sender(); + QStringList lines = QString(socket->readAll()).split('\n'); + QString fileName; + + fileName = lines[0]; + lines.removeFirst(); + + QFile file(fileName); + if (file.open(QIODevice::Append)) { + for (int line = 0; line < lines.size(); ++ line) { + file.write((lines[line] + '\n').toLocal8Bit()); + } + } + + file.close(); +} diff --git a/Lesson_6/Task_1/Server/server.h b/Lesson_6/Task_1/Server/server.h new file mode 100644 index 0000000..a14046b --- /dev/null +++ b/Lesson_6/Task_1/Server/server.h @@ -0,0 +1,38 @@ +#ifndef SERVER_H +#define SERVER_H + +#include +#include +#include +#include +#include +#include +#include + +class Server : public QObject +{ + Q_OBJECT +public: + explicit Server(QObject *parent = nullptr); + ~Server(); + +public slots: + void start(QString host, int port); + +private slots: + void newClient(); + void leftClient(); + void messageFromClient(); +signals: + +private: + QTcpServer *m_server = nullptr; + QVector m_clients; + bool isInfoGot = false; + QString fileName; + int fileSize; + +signals: +}; + +#endif // SERVER_H diff --git a/README.md b/README.md index 6b3acfa..2238eee 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,11 @@ Checked means the task is Done. ### Lesson 5 +- [x] Task 1 +- [x] Task 2 +- [x] Task 3 +- [x] Task 4 + +### Lesson 6 + - [ ] Task 1 -- [ ] Task 2 -- [ ] Task 3 -- [ ] Task 4