From 3538de7f4ebd325e6d36711dc057a73e1deee038 Mon Sep 17 00:00:00 2001 From: taynpg Date: Sun, 15 Jun 2025 20:37:25 +0800 Subject: [PATCH] communicate: basic server and client communicate. --- ClientCore/ClientCore.cpp | 24 +++++++++++++++++ ClientCore/ClientCore.h | 3 +++ Gui/Control/CompareControl.h | 6 ++--- Gui/Control/ConnectControl.cpp | 48 ++++++++++++++++++---------------- Gui/Control/ConnectControl.h | 33 +++++++++++++++++++---- Gui/Control/FileControl.cpp | 6 ----- Gui/Control/FileControl.h | 3 --- Gui/Control/LogControl.cpp | 2 +- Gui/GuiUtil/Public.h | 2 +- Gui/frelayGUI.cpp | 36 ++++++++++++++++++++----- Gui/frelayGUI.h | 4 ++- Gui/main.cpp | 2 ++ Server/CMakeLists.txt | 2 +- Server/Server.cpp | 31 ++++++++++++++-------- Server/Server.h | 1 + Server/main.cpp | 4 +++ Util/Util.cpp | 2 ++ 17 files changed, 147 insertions(+), 62 deletions(-) diff --git a/ClientCore/ClientCore.cpp b/ClientCore/ClientCore.cpp index f98c037..69ef6fd 100644 --- a/ClientCore/ClientCore.cpp +++ b/ClientCore/ClientCore.cpp @@ -1,9 +1,14 @@ #include "ClientCore.h" +#include +#include #include ClientCore::ClientCore(QObject* parent) : QObject(parent) { + socket_ = new QTcpSocket(this); + connect(socket_, &QTcpSocket::readyRead, this, &ClientCore::onReadyRead); + connect(socket_, &QTcpSocket::disconnected, this, &ClientCore::onDisconnected); } ClientCore::~ClientCore() @@ -22,6 +27,7 @@ bool ClientCore::Connect(const QString& ip, quint16 port) qCritical() << QString(tr("%1:%2 connect failed...")).arg(ip).arg(port); return false; } + qInfo() << QString(tr("%1:%2 connected success.")).arg(ip).arg(port); return true; } @@ -49,6 +55,21 @@ void ClientCore::onDisconnected() void ClientCore::UseFrame(QSharedPointer frame) { + switch (frame->type) { + case FrameBufferType::FBT_SER_MSG_ASKCLIENTS: { + InfoClientVec info = infoUnpack(frame->data); + clientsCall_(info); + break; + } + case FrameBufferType::FBT_SER_MSG_YOURID: { + ownID_ = frame->data; + qInfo() << QString(tr("own id: %1")).arg(ownID_); + break; + } + default: + qWarning() << QString(tr("unknown frame type: %1")).arg(frame->type); + break; + } } bool ClientCore::Send(QSharedPointer frame) @@ -79,14 +100,17 @@ bool ClientCore::Send(const char* data, qint64 len) void ClientCore::SetClientsCall(const std::function& call) { + clientsCall_ = call; } void ClientCore::SetPathCall(const std::function& call) { + pathCall_ = call; } void ClientCore::SetFileCall(const std::function& call) { + fileCall_ = call; } void ClientCore::SetRemoteID(const QString& id) diff --git a/ClientCore/ClientCore.h b/ClientCore/ClientCore.h index 1e53958..61d1af3 100644 --- a/ClientCore/ClientCore.h +++ b/ClientCore/ClientCore.h @@ -41,11 +41,14 @@ public: public: QMutex conMutex_; + QString ownID_; QString remoteID_; QTcpSocket* socket_; QByteArray recvBuffer_; std::function pathCall_; + std::function clientsCall_; + std::function fileCall_; }; #endif // CLIENTCORE_H \ No newline at end of file diff --git a/Gui/Control/CompareControl.h b/Gui/Control/CompareControl.h index 3b4def3..9dd2405 100644 --- a/Gui/Control/CompareControl.h +++ b/Gui/Control/CompareControl.h @@ -12,11 +12,11 @@ class Compare : public QWidget Q_OBJECT public: - explicit Compare(QWidget *parent = nullptr); + explicit Compare(QWidget* parent = nullptr); ~Compare(); private: - Ui::Compare *ui; + Ui::Compare* ui; }; -#endif // COMPARECONTROL_H +#endif // COMPARECONTROL_H diff --git a/Gui/Control/ConnectControl.cpp b/Gui/Control/ConnectControl.cpp index fa8afb5..fa934ad 100644 --- a/Gui/Control/ConnectControl.cpp +++ b/Gui/Control/ConnectControl.cpp @@ -4,11 +4,10 @@ #include #include -#include "Control/LogControl.h" #include "GuiUtil/Public.h" #include "ui_ConnectControl.h" -Connecter::Connecter(QWidget* parent) : QWidget(parent), ui(new Ui::Connecter) +Connecter::Connecter(QWidget* parent) : QWidget(parent), ui(new Ui::Connecter), th_(nullptr) { ui->setupUi(this); InitControl(); @@ -16,9 +15,6 @@ Connecter::Connecter(QWidget* parent) : QWidget(parent), ui(new Ui::Connecter) Connecter::~Connecter() { - if (thConnect_.joinable()) { - thConnect_.join(); - } delete ui; } @@ -28,11 +24,6 @@ void Connecter::SetClientCore(ClientCore* clientCore) clientCore_->SetClientsCall([this](const InfoClientVec& clients) { HandleClients(clients); }); } -void Connecter::SetLogPrint(LogPrint* log) -{ - log_ = log; -} - void Connecter::SetRemoteCall(const std::function& call) { remoteCall_ = call; @@ -42,7 +33,7 @@ void Connecter::HandleClients(const InfoClientVec& clients) { model_->removeRows(0, ui->listView->model()->rowCount()); for (const auto& client : clients.vec) { - auto* item = new QStandardItem(client.name); + auto* item = new QStandardItem(client.id); model_->appendRow(item); } } @@ -55,19 +46,30 @@ void Connecter::Connect() FTCommon::msg(this, tr("IP or Port is empty.")); return; } - auto task = [this, ip, port]() { - emit sendConnect(ConnectState::CS_CONNECTING); - connceted_ = clientCore_->Connect(ip, port.toInt()); - if (connceted_) { - emit sendConnect(ConnectState::CS_CONNECTED); - } else { - emit sendConnect(ConnectState::CS_DISCONNECT); + + if (th_) { + if (th_->isRunning()) { + th_->quit(); + th_->wait(1000); } - }; - if (thConnect_.joinable()) { - thConnect_.join(); + delete th_; } - thConnect_ = std::thread(task); + + auto* worker = new ConnectWorker(clientCore_, nullptr); + th_ = new QThread(); + worker->moveToThread(th_); + clientCore_->moveToThread(th_); + + connect(th_, &QThread::started, + [this, worker, ip, port]() { worker->doConnect(ip, port.toInt(), this->parent()->thread()); }); + connect(worker, &ConnectWorker::connecting, this, [this]() { setState(ConnectState::CS_CONNECTING); }); + connect(worker, &ConnectWorker::connectResult, this, [this](bool success) { + emit sendConnect(success ? ConnectState::CS_CONNECTED : ConnectState::CS_DISCONNECT); + th_->quit(); + }); + connect(th_, &QThread::finished, worker, &QObject::deleteLater); + connect(th_, &QThread::finished, th_, &QObject::deleteLater); + th_->start(); } void Connecter::setState(ConnectState cs) @@ -76,7 +78,7 @@ void Connecter::setState(ConnectState cs) case CS_CONNECTING: ui->btnConnect->setEnabled(false); ui->btnDisconnect->setEnabled(false); - log_->Info(tr("Connecting...")); + qInfo() << QString(tr("Connecting...")); break; case CS_CONNECTED: ui->btnConnect->setEnabled(false); diff --git a/Gui/Control/ConnectControl.h b/Gui/Control/ConnectControl.h index 0ee0a27..e8f26e1 100644 --- a/Gui/Control/ConnectControl.h +++ b/Gui/Control/ConnectControl.h @@ -17,7 +17,6 @@ enum ConnectState { CS_CONNECTED, }; -class LogPrint; class Connecter : public QWidget { Q_OBJECT @@ -28,7 +27,6 @@ public: public: void SetClientCore(ClientCore* clientCore); - void SetLogPrint(LogPrint* log); void SetRemoteCall(const std::function& call); void HandleClients(const InfoClientVec& clients); @@ -44,10 +42,7 @@ private: std::string getCurClient(); private: - std::thread thConnect_; Ui::Connecter* ui; - LogPrint* log_; - bool thRun_{false}; bool connceted_{false}; std::thread thContext_; std::function remoteCall_; @@ -55,7 +50,35 @@ private: private: QMenu* menu_; + QThread* th_; + QThread* mainTh_; QStandardItemModel* model_; }; +class ConnectWorker : public QObject +{ + Q_OBJECT +public: + explicit ConnectWorker(ClientCore* clientCore, QObject* parent = nullptr) + : QObject(parent), clientCore_(clientCore) + { + } + +public slots: + void doConnect(const QString& ip, int port, QThread* parentThread) + { + emit connecting(); + bool connected = clientCore_->Connect(ip, port); + clientCore_->moveToThread(parentThread); + emit connectResult(connected); + } + +signals: + void connectResult(bool success); + void connecting(); + +private: + ClientCore* clientCore_; +}; + #endif // CONNECTCONTROL_H diff --git a/Gui/Control/FileControl.cpp b/Gui/Control/FileControl.cpp index b4635a0..87edcda 100644 --- a/Gui/Control/FileControl.cpp +++ b/Gui/Control/FileControl.cpp @@ -8,7 +8,6 @@ #include #include -#include "LogControl.h" #include "ui_FileControl.h" FileManager::FileManager(QWidget* parent) : QWidget(parent), ui(new Ui::FileManager) @@ -38,11 +37,6 @@ void FileManager::SetModeStr(const QString& modeStr, int type, ClientCore* clien } } -void FileManager::SetLogPrint(LogPrint* log) -{ - log_ = log; -} - void FileManager::InitControl() { QStringList headers; diff --git a/Gui/Control/FileControl.h b/Gui/Control/FileControl.h index 8bc72f6..a0d6e04 100644 --- a/Gui/Control/FileControl.h +++ b/Gui/Control/FileControl.h @@ -10,7 +10,6 @@ namespace Ui { class FileManager; } -class LogPrint; class FileManager : public QWidget { Q_OBJECT @@ -21,7 +20,6 @@ public: public: void SetModeStr(const QString& modeStr, int type = 0, ClientCore* clientCore = nullptr); - void SetLogPrint(LogPrint* log); private: void InitControl(); @@ -36,7 +34,6 @@ private: private: Ui::FileManager* ui; - LogPrint* log_; QString curRoot_; std::shared_ptr fileHelper_; }; diff --git a/Gui/Control/LogControl.cpp b/Gui/Control/LogControl.cpp index 317bf32..2e0f552 100644 --- a/Gui/Control/LogControl.cpp +++ b/Gui/Control/LogControl.cpp @@ -43,7 +43,7 @@ void LogPrint::Info(const QString& message) } void LogPrint::Warn(const QString& message) { - Print(message, Qt::yellow); + Print(message, Qt::gray); } void LogPrint::Error(const QString& message) { diff --git a/Gui/GuiUtil/Public.h b/Gui/GuiUtil/Public.h index ea7f690..c3f46c1 100644 --- a/Gui/GuiUtil/Public.h +++ b/Gui/GuiUtil/Public.h @@ -13,4 +13,4 @@ public: static QString GetAppPath(); }; -#endif // PUBLIC_H \ No newline at end of file +#endif // PUBLIC_H \ No newline at end of file diff --git a/Gui/frelayGUI.cpp b/Gui/frelayGUI.cpp index 3614fb2..b44889d 100644 --- a/Gui/frelayGUI.cpp +++ b/Gui/frelayGUI.cpp @@ -4,6 +4,8 @@ #include "./ui_frelayGUI.h" +static LogPrint* logPrint = nullptr; + frelayGUI::frelayGUI(QWidget* parent) : QMainWindow(parent), ui(new Ui::frelayGUI) { ui->setupUi(this); @@ -20,21 +22,17 @@ frelayGUI::~frelayGUI() void frelayGUI::InitControl() { - log_ = new LogPrint(this); - - clientCore_ = new ClientCore(this); + logPrint = new LogPrint(this); + clientCore_ = new ClientCore(); connecter_ = new Connecter(this); connecter_->SetClientCore(clientCore_); - connecter_->SetLogPrint(log_); connecter_->SetRemoteCall([this](const QString& id) { clientCore_->SetRemoteID(id); }); localFile_ = new FileManager(this); remoteFile_ = new FileManager(this); localFile_->SetModeStr(tr("Local:")); remoteFile_->SetModeStr(tr("Remote:"), 1, clientCore_); - localFile_->SetLogPrint(log_); - remoteFile_->SetLogPrint(log_); tabWidget_ = new QTabWidget(this); } @@ -57,7 +55,7 @@ void frelayGUI::ControlLayout() sTop->addWidget(tabWidget_); sTop->addWidget(connecter_); - tabWidget_->addTab(log_, tr("Log")); + tabWidget_->addTab(logPrint, tr("Log")); sFile->addWidget(localFile_); sFile->addWidget(remoteFile_); @@ -67,6 +65,30 @@ void frelayGUI::ControlLayout() setCentralWidget(splitter); } +void frelayGUI::ControlMsgHander(QtMsgType type, const QMessageLogContext& context, const QString& msg) +{ + Q_UNUSED(context); + + switch (type) { + case QtDebugMsg: + logPrint->Debug(msg); + break; + case QtInfoMsg: + logPrint->Info(msg); + break; + case QtWarningMsg: + logPrint->Warn(msg); + break; + case QtCriticalMsg: + case QtFatalMsg: + logPrint->Error(msg); + break; + default: + logPrint->Error("Unknown QtMsgType type."); + break; + } +} + void frelayGUI::closeEvent(QCloseEvent* event) { QMainWindow::closeEvent(event); diff --git a/Gui/frelayGUI.h b/Gui/frelayGUI.h index d8b7f96..9c13bd2 100644 --- a/Gui/frelayGUI.h +++ b/Gui/frelayGUI.h @@ -30,12 +30,14 @@ private: void ControlSignal(); void ControlLayout(); +public: + static void ControlMsgHander(QtMsgType type, const QMessageLogContext& context, const QString& msg); + protected: void closeEvent(QCloseEvent* event) override; private: Ui::frelayGUI* ui; - LogPrint* log_; QTabWidget* tabWidget_; Connecter* connecter_; FileManager* localFile_; diff --git a/Gui/main.cpp b/Gui/main.cpp index b18d4fa..2931e4f 100644 --- a/Gui/main.cpp +++ b/Gui/main.cpp @@ -7,6 +7,8 @@ int main(int argc, char* argv[]) { QApplication a(argc, argv); + qInstallMessageHandler(frelayGUI::ControlMsgHander); + #ifdef _WIN32 QFont font("Microsoft YaHei", 9); a.setFont(font); diff --git a/Server/CMakeLists.txt b/Server/CMakeLists.txt index e546675..7c04dd4 100644 --- a/Server/CMakeLists.txt +++ b/Server/CMakeLists.txt @@ -13,5 +13,5 @@ find_package(QT NAMES Qt6 Qt5 REQUIRED COMPONENTS Core Network) find_package(Qt${QT_VERSION_MAJOR} REQUIRED COMPONENTS Core Network) add_executable(frelayServer Server.h Server.cpp main.cpp) -target_link_libraries(frelayServer PRIVATE Protocol) +target_link_libraries(frelayServer PRIVATE Protocol Util) target_link_libraries(frelayServer PRIVATE Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) \ No newline at end of file diff --git a/Server/Server.cpp b/Server/Server.cpp index 9692142..2666086 100644 --- a/Server/Server.cpp +++ b/Server/Server.cpp @@ -10,6 +10,7 @@ Server::Server(QObject* parent) : QTcpServer(parent) { monitorTimer_ = new QTimer(this); connect(monitorTimer_, &QTimer::timeout, this, &Server::monitorClients); + connect(this, &Server::newConnection, this, &Server::onNewConnection); } Server::~Server() @@ -26,6 +27,7 @@ bool Server::startServer(quint16 port) qDebug() << "Server started on port" << serverPort(); monitorTimer_->start(30000); + id_ = QString("0.0.0.0:%1").arg(serverPort()); return true; } @@ -45,7 +47,11 @@ void Server::stopServer() void Server::onNewConnection() { QTcpSocket* clientSocket = nextPendingConnection(); - QString clientId = QString("%1:%2").arg(clientSocket->peerAddress().toString()).arg(clientSocket->peerPort()); + + QHostAddress peerAddress = clientSocket->peerAddress(); + quint32 ipv4 = peerAddress.toIPv4Address(); + QString ipStr = QHostAddress(ipv4).toString(); + QString clientId = QString("%1:%2").arg(ipStr).arg(clientSocket->peerPort()); if (clients_.size() >= 100) { qWarning() << "Client connection refused (max limit reached):" << clientId; @@ -55,6 +61,7 @@ void Server::onNewConnection() auto client = QSharedPointer::create(); client->socket = clientSocket; + client->socket->setProperty("clientId", clientId); client->id = clientId; client->connectTime = QDateTime::currentSecsSinceEpoch(); @@ -69,9 +76,9 @@ void Server::onNewConnection() qDebug() << "Client connected:" << clientId; auto frame = QSharedPointer::create(); frame->type = FBT_SER_MSG_YOURID; - frame->fid = "server"; + frame->fid = id_; frame->tid = clientId; - frame->data = QString("Welcome client %1").arg(clientId).toUtf8(); + frame->data = clientId.toUtf8(); sendData(clientSocket, frame); } @@ -82,7 +89,10 @@ void Server::onClientDisconnected() return; } - QString clientId = QString("%1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort()); + QHostAddress peerAddress = socket->peerAddress(); + quint32 ipv4 = peerAddress.toIPv4Address(); + QString ipStr = QHostAddress(ipv4).toString(); + QString clientId = QString("%1:%2").arg(ipStr).arg(socket->peerPort()); { QWriteLocker locker(&rwLock_); @@ -100,12 +110,10 @@ void Server::onReadyRead() return; } - QString clientId = QString("%1:%2").arg(socket->peerAddress().toString()).arg(socket->peerPort()); - QSharedPointer client; { QReadLocker locker(&rwLock_); - client = clients_.value(clientId); + client = clients_.value(socket->property("clientId").toString()); } if (client) { @@ -147,7 +155,7 @@ bool Server::forwardData(QSharedPointer client, QSharedPointer::create(); errorFrame->type = FBT_SER_MSG_FORWARD_FAILED; - errorFrame->fid = "server"; + errorFrame->fid = id_; errorFrame->tid = client->id; errorFrame->data = QString("Target client %1 not found").arg(frame->tid).toUtf8(); return sendData(client->socket, errorFrame); @@ -160,11 +168,12 @@ void Server::replyRequest(QSharedPointer client, QSharedPointer::create(); - replyFrame->type = FBT_SER_MSG_RESPONSE; - replyFrame->fid = "server"; + replyFrame->type = FBT_SER_MSG_ASKCLIENTS; + replyFrame->fid = id_; replyFrame->tid = client->id; replyFrame->data = clientList; - sendData(client->socket, replyFrame); + auto ret = sendData(client->socket, replyFrame); + qDebug() << "Reply client list:" << client->id << ret; break; } default: diff --git a/Server/Server.h b/Server/Server.h index 304b9cf..ae6541d 100644 --- a/Server/Server.h +++ b/Server/Server.h @@ -42,6 +42,7 @@ private: void replyRequest(QSharedPointer client, QSharedPointer frame); bool sendData(QTcpSocket* socket, QSharedPointer frame); + QString id_; QMap> clients_; QReadWriteLock rwLock_; QTimer* monitorTimer_; diff --git a/Server/main.cpp b/Server/main.cpp index b508d0c..28ed8b7 100644 --- a/Server/main.cpp +++ b/Server/main.cpp @@ -1,11 +1,15 @@ #include #include "Server.h" +#include int main(int argc, char* argv[]) { QCoreApplication app(argc, argv); + Util::InitLogger("frelayServer.log", "frelayServer"); + qInstallMessageHandler(Util::ConsoleMsgHander); + Server server; if (!server.startServer(9009)) { return 1; diff --git a/Util/Util.cpp b/Util/Util.cpp index 92d4e2b..a7a3563 100644 --- a/Util/Util.cpp +++ b/Util/Util.cpp @@ -66,8 +66,10 @@ QString DirFileHelper::GetErr() const void DirFileHelper::registerPathCall(const std::function& call) { + pathCall_ = call; } void DirFileHelper::registerFileCall(const std::function& call) { + fileCall_ = call; }