Connection timed out when using QTcpSocket
-
I'm trying to create a TCP socket connection using
QTcpSocket
, it's working correctly when I use alocal ip
, but when I try with mypublic ip
it doesn't.After
some
time it throws an error:"Connection timed out"
.I'm not sure if this has something with the Windows Firewall, I have added both server and client to the "Allowed apps" of the firewall and also tried temporarily turning the firewall off, but the error persists.
I'm able to ping my public IP from different networks.
I also tested the sample below on a different machine/network and got the same error.How could i troubleshoot this?
server
#include <QNetworkInterface> #include <QTcpSocket> #include <QTcpServer> class Server : public QDialog { Q_OBJECT public: explicit Server(QWidget* parent = nullptr) : QDialog(parent), statusLabel(new QLabel) { statusLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); initServer(); fortunes << tr("You've been leading a dog's life. Stay off the furniture.") << tr("You've got to think about tomorrow.") << tr("You will be surprised by a loud noise."); auto quitButton = new QPushButton(tr("Quit")); quitButton->setAutoDefault(false); connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close); connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune); auto buttonLayout = new QHBoxLayout; buttonLayout->addStretch(1); buttonLayout->addWidget(quitButton); buttonLayout->addStretch(1); QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->addWidget(statusLabel); mainLayout->addLayout(buttonLayout); setWindowTitle(QGuiApplication::applicationDisplayName()); } private slots: void sendFortune() { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_6_5); out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())]; QTcpSocket* clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, &QAbstractSocket::disconnected, clientConnection, &QObject::deleteLater); clientConnection->write(block); clientConnection->disconnectFromHost(); } private: void initServer() { tcpServer = new QTcpServer(this); if (!tcpServer->listen(QHostAddress("tcp://000.000.000.000"))) { QMessageBox::critical(this, tr("Fortune Server"), tr("Unable to start the server: %1.").arg(tcpServer->errorString())); close(); return; } QString ipAddress = "000.000.000.000"; statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n" "Run the Fortune Client example now.").arg(ipAddress).arg(tcpServer->serverPort())); } QLabel *statusLabel = nullptr; QTcpServer *tcpServer = nullptr; QList<QString> fortunes; }; int main(int argc, char *argv[]) { QApplication::setApplicationDisplayName(Server::tr("Fortune Server")); Server server; server.show(); return a.exec(); }
client
#pragma once #include <QtNetwork> #include <QNetworkInterface> #include <QTcpSocket> #include <QTcpServer> class Client : public QDialog { Q_OBJECT public: explicit Client(QWidget* parent = nullptr) : QDialog(parent), hostCombo(new QComboBox), portLineEdit(new QLineEdit), getFortuneButton(new QPushButton(tr("Get Fortune"))), tcpSocket(new QTcpSocket(this)) { hostCombo->setEditable(true); hostCombo->addItem(QString("000.000.000.000")); portLineEdit->setValidator(new QIntValidator(1, 65535, this)); auto hostLabel = new QLabel(tr("&Server name:")); hostLabel->setBuddy(hostCombo); auto portLabel = new QLabel(tr("S&erver port:")); portLabel->setBuddy(portLineEdit); statusLabel = new QLabel(tr("This examples requires that you run the " "Fortune Server example as well.")); getFortuneButton->setDefault(true); getFortuneButton->setEnabled(false); auto quitButton = new QPushButton(tr("Quit")); auto buttonBox = new QDialogButtonBox; buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); in.setDevice(tcpSocket); in.setVersion(QDataStream::Qt_6_5); connect(hostCombo, &QComboBox::editTextChanged, this, &Client::enableGetFortuneButton); connect(portLineEdit, &QLineEdit::textChanged, this, &Client::enableGetFortuneButton); connect(getFortuneButton, &QAbstractButton::clicked, this, &Client::requestNewFortune); connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close); connect(tcpSocket, &QIODevice::readyRead, this, &Client::readFortune); connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &Client::displayError); QGridLayout* mainLayout = mainLayout = new QGridLayout(this); mainLayout->addWidget(hostLabel, 0, 0); mainLayout->addWidget(hostCombo, 0, 1); mainLayout->addWidget(portLabel, 1, 0); mainLayout->addWidget(portLineEdit, 1, 1); mainLayout->addWidget(statusLabel, 2, 0, 1, 2); mainLayout->addWidget(buttonBox, 3, 0, 1, 2); setWindowTitle(QGuiApplication::applicationDisplayName()); portLineEdit->setFocus(); } private slots: void requestNewFortune() { getFortuneButton->setEnabled(false); tcpSocket->abort(); tcpSocket->connectToHost(hostCombo->currentText(), portLineEdit->text().toInt()); } void readFortune() { in.startTransaction(); QString nextFortune; in >> nextFortune; if (!in.commitTransaction()) return; if (nextFortune == currentFortune) { QTimer::singleShot(0, this, &Client::requestNewFortune); return; } currentFortune = nextFortune; statusLabel->setText(currentFortune); getFortuneButton->setEnabled(true); } void displayError(QAbstractSocket::SocketError socketError) { switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: QMessageBox::information(this, tr("Fortune Client"), tr("The host was not found. Please check the " "host name and port settings.")); break; case QAbstractSocket::ConnectionRefusedError: QMessageBox::information(this, tr("Fortune Client"), tr("The connection was refused by the peer. " "Make sure the fortune server is running, " "and check that the host name and port " "settings are correct.")); break; default: QMessageBox::information(this, tr("Fortune Client"), tr("The following error occurred: %1.") .arg(tcpSocket->errorString())); } getFortuneButton->setEnabled(true); } void enableGetFortuneButton() { getFortuneButton->setEnabled(!hostCombo->currentText().isEmpty() && !portLineEdit->text().isEmpty()); } private: QComboBox *hostCombo = nullptr; QLineEdit *portLineEdit = nullptr; QLabel *statusLabel = nullptr; QPushButton *getFortuneButton = nullptr; QTcpSocket *tcpSocket = nullptr; QDataStream in; QString currentFortune; }; int main(int argc, char *argv[]) { QApplication::setApplicationDisplayName(Client::tr("Fortune Client")); Client client; client.show(); return a.exec(); }
Qt 6.5, Windows 10.
-
I'm trying to create a TCP socket connection using
QTcpSocket
, it's working correctly when I use alocal ip
, but when I try with mypublic ip
it doesn't.After
some
time it throws an error:"Connection timed out"
.I'm not sure if this has something with the Windows Firewall, I have added both server and client to the "Allowed apps" of the firewall and also tried temporarily turning the firewall off, but the error persists.
I'm able to ping my public IP from different networks.
I also tested the sample below on a different machine/network and got the same error.How could i troubleshoot this?
server
#include <QNetworkInterface> #include <QTcpSocket> #include <QTcpServer> class Server : public QDialog { Q_OBJECT public: explicit Server(QWidget* parent = nullptr) : QDialog(parent), statusLabel(new QLabel) { statusLabel->setTextInteractionFlags(Qt::TextBrowserInteraction); initServer(); fortunes << tr("You've been leading a dog's life. Stay off the furniture.") << tr("You've got to think about tomorrow.") << tr("You will be surprised by a loud noise."); auto quitButton = new QPushButton(tr("Quit")); quitButton->setAutoDefault(false); connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close); connect(tcpServer, &QTcpServer::newConnection, this, &Server::sendFortune); auto buttonLayout = new QHBoxLayout; buttonLayout->addStretch(1); buttonLayout->addWidget(quitButton); buttonLayout->addStretch(1); QVBoxLayout* mainLayout = new QVBoxLayout(this); mainLayout->addWidget(statusLabel); mainLayout->addLayout(buttonLayout); setWindowTitle(QGuiApplication::applicationDisplayName()); } private slots: void sendFortune() { QByteArray block; QDataStream out(&block, QIODevice::WriteOnly); out.setVersion(QDataStream::Qt_6_5); out << fortunes[QRandomGenerator::global()->bounded(fortunes.size())]; QTcpSocket* clientConnection = tcpServer->nextPendingConnection(); connect(clientConnection, &QAbstractSocket::disconnected, clientConnection, &QObject::deleteLater); clientConnection->write(block); clientConnection->disconnectFromHost(); } private: void initServer() { tcpServer = new QTcpServer(this); if (!tcpServer->listen(QHostAddress("tcp://000.000.000.000"))) { QMessageBox::critical(this, tr("Fortune Server"), tr("Unable to start the server: %1.").arg(tcpServer->errorString())); close(); return; } QString ipAddress = "000.000.000.000"; statusLabel->setText(tr("The server is running on\n\nIP: %1\nport: %2\n\n" "Run the Fortune Client example now.").arg(ipAddress).arg(tcpServer->serverPort())); } QLabel *statusLabel = nullptr; QTcpServer *tcpServer = nullptr; QList<QString> fortunes; }; int main(int argc, char *argv[]) { QApplication::setApplicationDisplayName(Server::tr("Fortune Server")); Server server; server.show(); return a.exec(); }
client
#pragma once #include <QtNetwork> #include <QNetworkInterface> #include <QTcpSocket> #include <QTcpServer> class Client : public QDialog { Q_OBJECT public: explicit Client(QWidget* parent = nullptr) : QDialog(parent), hostCombo(new QComboBox), portLineEdit(new QLineEdit), getFortuneButton(new QPushButton(tr("Get Fortune"))), tcpSocket(new QTcpSocket(this)) { hostCombo->setEditable(true); hostCombo->addItem(QString("000.000.000.000")); portLineEdit->setValidator(new QIntValidator(1, 65535, this)); auto hostLabel = new QLabel(tr("&Server name:")); hostLabel->setBuddy(hostCombo); auto portLabel = new QLabel(tr("S&erver port:")); portLabel->setBuddy(portLineEdit); statusLabel = new QLabel(tr("This examples requires that you run the " "Fortune Server example as well.")); getFortuneButton->setDefault(true); getFortuneButton->setEnabled(false); auto quitButton = new QPushButton(tr("Quit")); auto buttonBox = new QDialogButtonBox; buttonBox->addButton(getFortuneButton, QDialogButtonBox::ActionRole); buttonBox->addButton(quitButton, QDialogButtonBox::RejectRole); in.setDevice(tcpSocket); in.setVersion(QDataStream::Qt_6_5); connect(hostCombo, &QComboBox::editTextChanged, this, &Client::enableGetFortuneButton); connect(portLineEdit, &QLineEdit::textChanged, this, &Client::enableGetFortuneButton); connect(getFortuneButton, &QAbstractButton::clicked, this, &Client::requestNewFortune); connect(quitButton, &QAbstractButton::clicked, this, &QWidget::close); connect(tcpSocket, &QIODevice::readyRead, this, &Client::readFortune); connect(tcpSocket, &QAbstractSocket::errorOccurred, this, &Client::displayError); QGridLayout* mainLayout = mainLayout = new QGridLayout(this); mainLayout->addWidget(hostLabel, 0, 0); mainLayout->addWidget(hostCombo, 0, 1); mainLayout->addWidget(portLabel, 1, 0); mainLayout->addWidget(portLineEdit, 1, 1); mainLayout->addWidget(statusLabel, 2, 0, 1, 2); mainLayout->addWidget(buttonBox, 3, 0, 1, 2); setWindowTitle(QGuiApplication::applicationDisplayName()); portLineEdit->setFocus(); } private slots: void requestNewFortune() { getFortuneButton->setEnabled(false); tcpSocket->abort(); tcpSocket->connectToHost(hostCombo->currentText(), portLineEdit->text().toInt()); } void readFortune() { in.startTransaction(); QString nextFortune; in >> nextFortune; if (!in.commitTransaction()) return; if (nextFortune == currentFortune) { QTimer::singleShot(0, this, &Client::requestNewFortune); return; } currentFortune = nextFortune; statusLabel->setText(currentFortune); getFortuneButton->setEnabled(true); } void displayError(QAbstractSocket::SocketError socketError) { switch (socketError) { case QAbstractSocket::RemoteHostClosedError: break; case QAbstractSocket::HostNotFoundError: QMessageBox::information(this, tr("Fortune Client"), tr("The host was not found. Please check the " "host name and port settings.")); break; case QAbstractSocket::ConnectionRefusedError: QMessageBox::information(this, tr("Fortune Client"), tr("The connection was refused by the peer. " "Make sure the fortune server is running, " "and check that the host name and port " "settings are correct.")); break; default: QMessageBox::information(this, tr("Fortune Client"), tr("The following error occurred: %1.") .arg(tcpSocket->errorString())); } getFortuneButton->setEnabled(true); } void enableGetFortuneButton() { getFortuneButton->setEnabled(!hostCombo->currentText().isEmpty() && !portLineEdit->text().isEmpty()); } private: QComboBox *hostCombo = nullptr; QLineEdit *portLineEdit = nullptr; QLabel *statusLabel = nullptr; QPushButton *getFortuneButton = nullptr; QTcpSocket *tcpSocket = nullptr; QDataStream in; QString currentFortune; }; int main(int argc, char *argv[]) { QApplication::setApplicationDisplayName(Client::tr("Fortune Client")); Client client; client.show(); return a.exec(); }
Qt 6.5, Windows 10.
"how can I troubleshoot this?" is an extremely broad question. There is no such thing as a "local IP". There are public and private IPs. Private IPs are behind a NAT firewall, usually.
You don't give enough information about your network environment to say for sure, but I'll wager your problems have nothing to do with Qt, but are due to a lack of understanding of the network config side of things.
-
"how can I troubleshoot this?" is an extremely broad question. There is no such thing as a "local IP". There are public and private IPs. Private IPs are behind a NAT firewall, usually.
You don't give enough information about your network environment to say for sure, but I'll wager your problems have nothing to do with Qt, but are due to a lack of understanding of the network config side of things.
@Kent-Dorfman said in Connection timed out when using QTcpSocket:
You don't give enough information about your network environment
Sure, what information about my network environment could help troubleshoot this issue?
Im testing the code into two completely different machines/network, and getting the same error. -
@Kent-Dorfman said in Connection timed out when using QTcpSocket:
You don't give enough information about your network environment
Sure, what information about my network environment could help troubleshoot this issue?
Im testing the code into two completely different machines/network, and getting the same error.@n34rt
what host/ip is the server running on?
what host/ip is the client running on?
what network exists between them? same network subnet? NAT translation?You do understand that you cannot talk to a NAT machine behind a firewall using the public IP address without doing something called port forwarding in the router?
-
@n34rt
what host/ip is the server running on?
what host/ip is the client running on?
what network exists between them? same network subnet? NAT translation?You do understand that you cannot talk to a NAT machine behind a firewall using the public IP address without doing something called port forwarding in the router?
@Kent-Dorfman said in Connection timed out when using QTcpSocket:
You do understand that you cannot talk to a NAT machine behind a firewall using the public IP address without doing something called port forwarding in the router?
I didn't, thank you for pointing this, I'm completely new in networking, sockets, etc.
I was searching more about, would it work if I host a local server with something like apache?
-
@Kent-Dorfman said in Connection timed out when using QTcpSocket:
You do understand that you cannot talk to a NAT machine behind a firewall using the public IP address without doing something called port forwarding in the router?
I didn't, thank you for pointing this, I'm completely new in networking, sockets, etc.
I was searching more about, would it work if I host a local server with something like apache?
@n34rt said in Connection timed out when using QTcpSocket:
I was searching more about, would it work if I host a local server with something like apache?
no. that's the whole purpose of consumer grade internet connectivity via NAT routers: to keep customers from running services without paying for commercial grade service.
-
@n34rt said in Connection timed out when using QTcpSocket:
I was searching more about, would it work if I host a local server with something like apache?
no. that's the whole purpose of consumer grade internet connectivity via NAT routers: to keep customers from running services without paying for commercial grade service.
@Kent-Dorfman even if I open the required ports to the apache server in my router?