Solved QTcpServer::newConnection() does not work when realized in another class
-
As title, my purpose is open the listen and when a new connection is coming, do something.
I don't want to write all my functions in the mainwindow, so I create another class to realize this function.
as my coding follow, I used the first kind of init(), but it does not work, I try in the second init(), it works.I want to know why can you tell me? this is part codes in my 2 files.
mainwindow.cpp
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); ui->label->setText("Disconnected!"); ui->pushButton_send->setEnabled(false); bool isInitialized; // the first kind of init to open listen and get connection, init() is in another class called Server Server server; isInitialized = server.init(); // the second method to open listen and get connection, init() is in the same class isInitialized = init(); qDebug()<<isInitialized; } int MainWindow::init() { server = new QTcpServer(); connect(server, SIGNAL(newConnection()), this, SLOT(server_New_Connect())); int port = 5007; if(!server->listen(QHostAddress::Any,port)) { ui->label_listen->setText("fail to listen"); qDebug()<<server->errorString(); return 0; } ui->label_listen->setText("listen succeed"); return 1; }
Server.cpp
bool Server::init() { bool isInitialized = listen(QHostAddress(SERVER_IP), SERVER_PORT); if (isInitialized) { m_serverStatus = SERVER_STATUS_OK; QThreadPool::globalInstance()->setMaxThreadCount(QTNConst::NUM_MAX_CLIENTS); connect(this, SIGNAL(newConnection()), this, SLOT(onNewConnection())); } return isInitialized; }
-
@gaosiy
it's very confused...
Why are you trying to create 2 QTcpServer (maybe in same port) ? i suppose that Server Class is a derived from QTcpServer -
thanks for replay
when I use this code, I will use just one of these.
I show all of them cause it will be clear. -
@gaosiy
I tested an similiar example:void Server::init() { bool isListening = listen(QHostAddress("127.0.0.1"), 5007); if(isListening){ qDebug() << "IS LISTENING"; connect(this, SIGNAL(newConnection()), this, SLOT(onNewConnection())); } } void Server::onNewConnection() { qDebug() << "Incoming Connection"; }
The newConnection signal is invoking onNewConnection normaly.
Note: If your class should use signal and slot feature, you need to define Q_OBJECT macro.
class Server : public QTcpServer{ Q_OBJECT // your derivered class implementation public: Server(); };
-
@KillerSmath said in QTcpServer::newConnection() does not work when realized in another class:
Q_OBJECT
thanks again!
I can also work it when test in a console application.
but in mainwindow (with ui), it does not work. -
@gaosiy
What exactly do you pretent to change or access on mainwindow ?You can capture the Server newConnection Signal and invoke a MainWindow slots as onNewConnectionServer()
///// //h file ///// class MainWindow : public QMainWindow { Q_OBJECT public: explicit MainWindow(QWidget *parent = 0); ~MainWindow(); private slots: void onNewConnectionServer(); private: Ui::MainWindow *ui; Server server; }; //// // cpp file ////// MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow) { ui->setupUi(this); connect(&server, SIGNAL(newConnection()), this, SLOT(onNewConnectionServer())); server.init(); } MainWindow::~MainWindow() { delete ui; } void MainWindow::onNewConnectionServer() { // acess ui }
-
@KillerSmath said in QTcpServer::newConnection() does not work when realized in another class:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);connect(&server, SIGNAL(newConnection()), this, SLOT(onNewConnectionServer())); server.init();
}
thanks!
in this code, can the nowconnection in the connect work if you put it in init() in another class?
I know it can work if I put it in the constructor directly -
@gaosiy
You can... but it is strange idea...2 Ways to achieve it:
- Storage a pointer to MainWindow object
- Pass MainWindow as Parent of Server Object
Example of how you could implement it by Parent Method:
MainWindow::MainWindow() { ... Server *server = new Server(this); server->init(); ... }
Change Server construtor to receive QObject pointer
class Server : public QTcpServer { Q_OBJECT public: Server(QObject *parent); ~Server(); void init(); };
Call QTcpServer Construtor (Base Class) passing parent
Server::Server(QObject *parent) : QTcpServer(parent) // call QTcpServer construtor { }
Cast the parent to MainWindow (parent) and create the connection
void Server::init() { bool isListening = listen(QHostAddress("127.0.0.1"), 5007); if(isListening){ MainWindow *window = qobject_cast<MainWindow*>(parent()); connect(this, SIGNAL(newConnection()), window, SLOT(onNewConnectionServer())); } }
But why necessarily do you need to create the connection inside of Init function ?
-
thanks.
I can show you why i want to achieve it at the other class.
this file is my first version of tcp communication without any UI//QTNetworkDemo.cpp #include "QTNetworkDemo.h" #include "client/QTNClient.h" #include "server/QTNServer.h" #include <QTNConst.h> QTNetworkDemo::QTNetworkDemo(int argc, char *argv[]) : QCoreApplication(argc, argv), CLIENT_CHOICE_STR(QTNConst::CLIENT_CHOICE_STR), SERVER_CHOICE_STR(QTNConst::SERVER_CHOICE_STR), EXIT_CHOICE_STR(QTNConst::EXIT_CHOICE_STR), m_opCode(OP_CODE_ERROR) { } int QTNetworkDemo::exec() { bool isInitialized; QTNServer server; qDebug()<<"1"<<endl; isInitialized = server.init(); return QCoreApplication::exec(); } int main(int argc, char *argv[]) { QTNetworkDemo demo(argc, argv); return demo.exec(); }
and this is server.cpp
// QTNServer.cpp #include "QTNServer.h" #include "QTNServerThread.h" #include <QTNConst.h> #include <QTcpSocket> #include <QStringList> #include <QTimer> #include <QThreadPool> QTNServer::QTNServer() : SERVER_IP(QTNConst::SERVER_IP), SERVER_PORT(QTNConst::SERVER_PORT), m_serverStatus(SERVER_STATUS_IDLE), m_numMaxClients(QTNConst::NUM_MAX_CLIENTS) { } bool QTNServer::init() { std::cout << getStatusDescription().c_str() << "is initializing " << "ip: " << SERVER_IP << ", port: " << SERVER_PORT << "\n"; bool isInitialized = listen(QHostAddress(SERVER_IP), SERVER_PORT); if (isInitialized) { m_serverStatus = SERVER_STATUS_OK; std::cout << getStatusDescription().c_str() << "is listening\n"; QThreadPool::globalInstance()->setMaxThreadCount(QTNConst::NUM_MAX_CLIENTS); connect(this, SIGNAL(newConnection()), this, SLOT(onNewConnection())); QTimer::singleShot(1000, this, SLOT(printClients())); } else { m_serverStatus = SERVER_STATUS_NOK; std::cout << getStatusDescription().c_str() << "is NOT listening\n"; } return isInitialized; }
when I use the first version, it works well.
but when I want to use TCP communication with UI, the same way of my method does not work
so I fell very strange and I can't understand why... -
And I find when I do like this in exec()
//return QCoreApplication::exec();
it does not work as the UI version.
I dont know why. -
@gaosiy said in QTcpServer::newConnection() does not work when realized in another class:
but when I want to use TCP communication with UI, the same way of my method does not work
You should not do it same way in a UI application: your UI application will already have an event loop.
Doing the connect in MainWindow constructor (or its init() method) is perfectly valid and the right thing to do. Your server should not know anything about your UI, so it can't do the connect to UI as it does not know anything about it :-)