Hello, I am writing a client-server application. As a result, for each connection I want to take a stream from QThreadPool ... this is still a draft, so the code is appropriate, but the server only sends data to the client, but receives nothing from it, although it should:
server.h:
#include <QTcpServer> #include <QAbstractSocket> #include <QTcpSocket> #include <QThreadPool> #include "tcpconnection.h" void log_(const QString& msg); class TcpServer_impl final : public QTcpServer { Q_OBJECT public: explicit TcpServer_impl(QObject* parent = nullptr); ~TcpServer_impl(); Q_SIGNALS: void createConnection(quintptr descriptor); protected: void incomingConnection(qintptr descriptor) override final; }; class CServer final : public QObject { Q_OBJECT public: CServer(std::size_t port, QObject *parent = nullptr); ~CServer(); void listen(); void stop(); void reload(); //void waitClients(); void setMaxThreads(size_t n); std::size_t getPort() { return m_Port; } enum STATE { STATE_INIT = 0, STATE_STOPPED, STATE_STARTED, STATE_RELOADED }; public Q_SLOTS: // обработчик входного соединения void connection_handler(quintptr descriptor); private: std::size_t m_Port = 0; STATE m_State; // QHash<int, QTcpSocket*> m_TcpClients; // Qhash<int, QLocalSocket*> m_USockClients; QHash<int, IConnection*> m_Connections; TcpServer_impl* m_Serv; QThreadPool* m_Pool; }; server.cpp:
#include "server.h" void log_(const QString &msg) { qDebug() << msg; } TcpServer_impl::TcpServer_impl(QObject *parent) : QTcpServer(parent) { } TcpServer_impl::~TcpServer_impl() { } void TcpServer_impl::incomingConnection(qintptr descriptor) { emit createConnection(descriptor); } CServer::CServer(std::size_t port, QObject* parent) : QObject(), m_Port(port), m_Serv(new TcpServer_impl(this)), m_State(STATE_INIT), m_Pool(new QThreadPool(this)) { connect(m_Serv, &TcpServer_impl::createConnection, this, &CServer::connection_handler); } void CServer::setMaxThreads(std::size_t n) { m_Pool->setMaxThreadCount(n); } CServer::~CServer() { m_Serv->close(); } void CServer::listen() { if(m_Serv->listen(QHostAddress::Any, m_Port)) { log_("server is started"); m_State = STATE_STARTED; } else { log_("Server: not started!"); //_Exit(1); } } //void CServer::waitClients() { // //ждем минуту, если нет соединений то заново // while(!m_Serv->waitForNewConnection(60000)) // { // int stop = 0; // int stop1 = 0; // } //} void CServer::connection_handler(quintptr descriptor) { if(m_State == STATE_STARTED) { IConnection* c = new CTcpConnection(descriptor, this); c->setAutoDelete(true); QThreadPool::globalInstance()->start(c); //m_Pool->start(c); } } void CServer::stop() { } void CServer::reload() { } connection.h:
#include <QThreadPool> #include <QTcpSocket> #include <QRunnable> class IConnection : public QObject, public QRunnable{ Q_OBJECT public: IConnection(QObject* parent = nullptr); virtual ~IConnection(); protected: void run() = 0; }; class CTcpConnection : public IConnection { Q_OBJECT public: explicit CTcpConnection(qintptr _descriptor); CTcpConnection(qintptr _descriptor, QObject* parent); ~CTcpConnection(); public Q_SLOTS: void onRead(); void onDisconnect(); void onWrite(const QString& data); protected: void run(); private: //QTcpSocket m_Sock; qintptr m_Descriptor; }; connection.cpp:
#include "connection.h" IConnection::IConnection(QObject *parent) : QObject(parent) { } IConnection::~IConnection() { } CTcpConnection::CTcpConnection(qintptr _descriptor) : IConnection(), m_Descriptor(_descriptor) { } CTcpConnection::CTcpConnection(qintptr _descriptor, QObject *parent) : IConnection(parent), m_Descriptor(_descriptor) { } CTcpConnection::~CTcpConnection() { //m_Sock.close(); } void CTcpConnection::onRead() { } void CTcpConnection::onWrite(const QString &data) { } void CTcpConnection::onDisconnect() { // m_Sock.close(); } void CTcpConnection::run() { QTcpSocket m_Sock; //connect(&m_Sock, &QTcpSocket::readyRead, this, &CTcpConnection::onRead, Qt::DirectConnection); connect(&m_Sock, &QTcpSocket::readyRead, this, [&m_Sock]{ std::cout << m_Sock.readAll().toStdString(); }, Qt::DirectConnection); connect(&m_Sock, &QTcpSocket::disconnected, this, &CTcpConnection::onDisconnect, Qt::DirectConnection); m_Sock.setSocketDescriptor(m_Descriptor); //этот блок ничего не принимает //while(m_Sock.bytesAvailable()>0) // { // QByteArray array = m_Sock.readAll(); // std::cout<<array.toStdString()<<std::endl; // m_Sock.write(array); // } m_Sock.write("From server: hello world"); m_Sock.flush(); } client.cpp:
#include <QCoreApplication> #include <QTcpSocket> #include <QHostAddress> #include <QDataStream> #include <QObject> #include <QThread> #include <iostream> int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); QTcpSocket *client = new QTcpSocket; QObject::connect(client, &QTcpSocket::connected, client, []{ std::cout<<"connected!!!\n"; }); QObject::connect(client, &QTcpSocket::disconnected, client, &QTcpSocket::deleteLater); QObject::connect(client, &QTcpSocket::readyRead, [&client]{ QByteArray arr = client->readAll(); std::cout<< arr.toStdString() << std::endl; }); client->connectToHost(QHostAddress::LocalHost, 1200); client->waitForConnected(); if (client->state() != QAbstractSocket::ConnectedState ) { qDebug() << Q_FUNC_INFO << " can't connect to host"; delete client; } QByteArray block; // QDataStream out(&block, QIODevice::WriteOnly); // out.setVersion(QDataStream::Qt_5_5); // out << QString("Hello, Server"); // out.device()->seek(0); // client->write(block); client->write("Hello, Server"); return a.exec(); } As a result, the client sends the data, and the server sends it the hello world, but accepts nothing from the client, i.e. Signal readyRead not emit ... tell me what the problem
update: added two fields to CTcpConnection: QTcpSocket * m_Sock; QEventLoop * m_Loop; and changed the run and onRead methods:
void CTcpConnection::onRead() { std::cout << m_Sock->readAll().toStdString() << " " << QThread::currentThreadId(); m_Sock->write("hello from server"); } void CTcpConnection::run() { m_Loop = new QEventLoop(); m_Sock = new QTcpSocket(); //QTcpSocket m_Sock; connect(m_Sock, &QTcpSocket::readyRead, this, &CTcpConnection::onRead, Qt::DirectConnection); connect(m_Sock, &QTcpSocket::disconnected, this, &CTcpConnection::onDisconnect, Qt::DirectConnection); m_Sock->setSocketDescriptor(m_Descriptor); m_Loop->exec(); delete m_Sock; delete m_Loop; } now we go to the onRead method, but nothing is output, but the client accepts hello from server ... what's the catch?
update: set the following to the onRead method:
qDebug << m_Sock->readAll().toStdString() << " " << QThread::currentThreadId(); and everything became output ... delivered CTcpConnect to the destructor ...
delete m_Sock; delete m_Loop; and I do not know how correct the decision is at all, that some kind of left eventloop is created in the run method ...