QT QTcpServer listen - qt

i have a question about QT QTcpServer server->listen(QHostAddress, qint16). I have problems with the address.
I tried with QHostAddress("127.0.0.1"), and that worked. I tried with QHostAddress::Any, and that failed (error 10, not supported). I tried with QHostAddress::AnyIPv4, and that failed (same error). I tried with QHostAddress("0.0.0.0"), and that failed, with same error. I tried with the address of the interface, that worked.
NotificationServer::NotificationServer(QObject *parent) : QObject(parent) {
server = new QTcpServer(this);
connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
if (!server->listen(QHostAddress::Any, port)) {
qDebug() << "Server could not start." << server->serverError();
server = nullptr;
} else {
qDebug() << "Server started.";
}
}
It seems, that it is not possible making the QTcpServer listen on all interfaces. OS is Linux XUbuntu. How can i make the server listen at all interfaces?

Related

How set QTcpServer listening alone on port using Win7

I use a QTcpServer that should listen alone on port. Language is c++ with Qt 5.9. The application must run under Win and Linux using MingW. The listen method from QTcpServer uses standard parameter for socket options. For Win10, Linux these options are set default to single usage of the listening port so listening works fine. Unfortunatly opposite to that Win7 offers shared usage which i must avoid.
I figured out that the QAbstractSocket class let me create a socket with the BindFlag::DontShareAddress. I can forward the socketdescriptor to the QTcpServer. Then the method listen fails (isn't listening) by stating: QTcpServer::listen() called when already listening. I check the ports status by using netstat.
My code sample is below:
bool TcpServer::init(QString ipAddress, quint16 port, Command::RoutingProperty clientSocketKind, QString interfaceName)
{
if (mServerIsInit == true) // only 1 server instance
{
return false;
mServer = new (std::nothrow) QTcpServer();
if (mServer == nullptr)
{
return false;
}
mClientSocketKind = clientSocketKind;
mInterfaceName = interfaceName;
// tries to set socket properties to a non sharing port
QTcpSocket tsocket;
if (!tsocket.bind(QHostAddress(ipAddress), port, QAbstractSocket::BindFlag::DontShareAddress))
{
qDebug() << "Socket bind fails";
}
else
{
qDebug() << "Socket bind success";
}
sd = tsocket.socketDescriptor(); // valid socket descriptor
if (!mServer->setSocketDescriptor(sd))
{
qDebug() << "SocketDescriptor fails";
}
sd = mServer->socketDescriptor();
qDebug() << "Socketdescriptor Server " << sd;
//end tries to set socket properties to a non sharing port
if (mServer->listen(QHostAddress(ipAddress), port)) // fails with message ... is always listening
// if (mServer->mServer->isListening()) // is not listening tells netstat
{
qDebug() << "Server status for listening ok: " << mServer->isListening();
qDebug() << "Server listen on " << mServer->serverAddress() << ":" << mServer->serverPort();
connect(mServer, SIGNAL(newConnection()), this, SLOT(newConnection()));
connect(mServer, SIGNAL(acceptError(QAbstractSocket::SocketError)), this, SLOT(socketErr(QAbstractSocket::SocketError)));
mServerIsInit = true;
return true;
}
else
{
qDebug() << "Server status for listening fail" << mServer->isListening();
delete mServer;
mServer = nullptr;
return false;
}
}
Thanks for any idea how to set the socket options for a exclusive usage of the listening port.
Martin
As per the comment, you will probably need to call listen explicitly on the socket descriptor before calling QTcpServer::setSocketDescriptor.
The following code is untested but should give you some idea...
if (!tsocket.bind(QHostAddress(ipAddress), port, QAbstractSocket::BindFlag::DontShareAddress))
{
qDebug() << "Socket bind fails";
}
else
{
qDebug() << "Socket bind success";
}
sd = tsocket.socketDescriptor(); // valid socket descriptor
/*
* Now make an explicit call to `listen' so that the socket descriptor
* can be passed to QTcpSocket::setSocketDescriptoy.
*/
if (listen(sd, SOMAXCONN) == SOCKET_ERROR)
{
printf("Listen failed with error: %ld\n", WSAGetLastError());
closesocket(sd);
WSACleanup();
/*
* Handle error.
*/
}
if (!mServer->setSocketDescriptor(sd))
{
qDebug() << "SocketDescriptor fails";
}
As an aside, note that you need to be a bit more careful with error handling -- simply call qDebug and continuing will come back to bite you at some point.

QT QTcpServer::incomingConnection(qintptr handle) not firing?

I'm trying to create a multithreaded server using Qt for the first time. Normally one would use the socket pointer returned by the QTcpServer::nextPendingConnection() with the socket handle already baked in - but since I'm interfacing with the connecting client on a separate thread, I need to create the socket separately using the qintptr handle from QTcpServer::incomingConnection(qintptr handle). After a very dreary, error-packed debugging session I managed to track down the problem to the QTcpServer::incomingConnection() never being fired?
Has anyone had a similar problem - has something changed over recent versions Qt?
These are the ones I've tried:
QTcpServer::incomingConnection(qintptr handle)
QTcpServer::incomingConnection(qintptr socketDescriptor)
QTcpServer::incomingConnection(int handle)
EDIT:
Creating instance of server:
TestServer *myServer = new TestServer();
myServer->initializeServer(1234);
Which calls:
void TestServer::initializeServer(quint16 port)
{
mainServer = new QTcpServer(this);
mainServer->listen(QHostAddress::Any, port);
qDebug() << "Listening for connections on port: " << port;
}
Server is now listening. When a client connects incomingConnection(qintptr handle) is supposed to be called:
void TestServer::incomingConnection(qintptr socketDescriptor){
TestClient *client = new TestClient(this);
client->setSocket(socketDescriptor);
}
Which calls:
void TestClient::setSocket(quint16 socketDescr)
{
socket = new QTcpSocket(this);
socket->setSocketDescriptor(socketDescr);
connect(socket, SIGNAL(connected()),this,SLOT(connected()));
connect(socket, SIGNAL(disconnected()),this,SLOT(disconnected()));
connect(socket, SIGNAL(readyRead()),this,SLOT(readyRead()));
}
Called on connect() signal:
void TestClient::connected()
{
qDebug() << "Client connected..."; // This debug never appears in the console, since QTcpServer::incomingConnection isn't being fired.
}
You have some errors at your code:
At TestServer your QTcpServer probably aggregated, but you need to inherit it. At this case you try to override incomingConnection() method, but you haven't base class and you just create new incomingConnection(), not override.
You get qintptr descriptor variable from incomingConnection(), but set quint16 type at setSocket() method.
You probably mix client of server and client of your part, which just get incoming connection and handling socket data.
I write some little example below for your understanding tcp client-server communication.
Server part
Main part is server themselves:
#include <QTcpServer>
class TestServer: public QTcpServer
{
public:
TestServer(QObject *parent = 0);
void incomingConnection(qintptr handle) Q_DECL_OVERRIDE;
};
Just look: I don't aggragate QTcpServer, but inherited it. At this case you can override incomingConnection() method correctly.
At constructor we just start server for listening using listen() method:
TestServer::TestServer(QObject *parent):
QTcpServer(parent)
{
if (this->listen(QHostAddress::Any, 2323)) {
qDebug() << "Server start at port: " << this->serverPort();
} else {
qDebug() << "Start failure";
}
}
Then time for overriding incomingConnection():
void TestServer::incomingConnection(qintptr handle)
{
qDebug() << Q_FUNC_INFO << " new connection";
SocketThread *socket = new SocketThread(handle);
connect(socket, SIGNAL(finished()), socket, SLOT(deleteLater()));
socket->start();
}
I create SocketThread object which handle incoming data:
#include <QThread>
#include <QObject>
class QTcpSocket;
class SocketThread: public QThread
{
Q_OBJECT
public:
SocketThread(qintptr descriptor, QObject *parent = 0);
~SocketThread();
protected:
void run() Q_DECL_OVERRIDE;
private slots:
void onConnected();
void onReadyRead();
void onDisconnected();
private:
QTcpSocket *m_socket;
qintptr m_descriptor;
};
We inherits from QThread for making our server multithreading, so we have to override run() method:
SocketThread::SocketThread(qintptr descriptor, QObject *parent)
: QThread(parent), m_descriptor(descriptor)
{
}
void SocketThread::run()
{
qDebug() << Q_FUNC_INFO;
m_socket = new QTcpSocket;
m_socket->setSocketDescriptor(m_descriptor);
connect(m_socket, SIGNAL(readyRead()), this, SLOT(onReadyRead()), Qt::DirectConnection);
connect(m_socket, SIGNAL(disconnected()), this, SLOT(onDisconnected()), Qt::DirectConnection);
exec();
}
This way we initialize our QTcpSocket, set socket descriptor, connect it with readyRead() and disconnected() signals and start event loop.
void SocketThread::onReadyRead()
{
QDataStream in(m_socket);
in.setVersion(QDataStream::Qt_5_5);
QString message;
in >> message;
qDebug() << message;
m_socket->disconnectFromHost();
}
void SocketThread::onDisconnected()
{
m_socket->close();
// Exit event loop
quit();
}
At onReadyRead() just read some QString from client, write it to console and disconnect from host. At onDisconnected() we close socket connection and exit event loop.
Client part
It is just example and bad-smells style, but i create connection to the server at MainWindow class on QPushButton::clicked signal:
void MainWindow::on_pushButton_clicked()
{
QTcpSocket *client = new QTcpSocket;
connect(client, SIGNAL(connected()), this, SLOT(connected()));
connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater()));
client->connectToHost(QHostAddress::LocalHost, 2323);
client->waitForConnected();
if (client->state() != QAbstractSocket::ConnectedState ) {
qDebug() << Q_FUNC_INFO << " can't connect to host";
delete client;
return;
}
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_5_5);
out << QString("Hello");
out.device()->seek(0);
client->write(block);
}
void MainWindow::connected()
{
qDebug() << Q_FUNC_INFO << " client connected";
}
I create new QTcpSocket, connect it to the signals and try to connect to the host(in my case it is localhost). Wait for connected and check socket status. If all is right I write to socket QString - just example.
It is one of possible ways to organized multithreading client-server architecture, i hope it will be helpfull for you and you find yours bugs.

Qt cannot connect to the server

I am trying to create simple server that will just show when somebody have connected to me. Everything works fine when client and server use "localhost" as a host name to connect, but when I changed localhost to my ip address then I got timeout error :(
There is my code:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
server_status=0;
}
void MainWindow::on_starting_clicked()
{
tcpServer = new QTcpServer(this);
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(newuser()));
if (!tcpServer->listen(QHostAddress::Any, 33333) && server_status==0) {
qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString());
ui->textinfo->append(tcpServer->errorString());
} else {
server_status=1;
qDebug() << tcpServer->isListening() << "TCPSocket listen on port";
ui->textinfo->append(QString::fromUtf8("Server started!"));
qDebug() << QString::fromUtf8("Server started!");
}
}
void MainWindow::on_stoping_clicked()
{
if(server_status==1){
foreach(int i,SClients.keys()){
QTextStream os(SClients[i]);
os.setAutoDetectUnicode(true);
os << QDateTime::currentDateTime().toString() << "\n";
SClients[i]->close();
SClients.remove(i);
}
tcpServer->close();
ui->textinfo->append(QString::fromUtf8("Server stopped!"));
qDebug() << QString::fromUtf8("Server stopped!");
server_status=0;
}
}
void MainWindow::newuser()
{
if(server_status==1){
qDebug() << QString::fromUtf8("New connection!");
ui->textinfo->append(QString::fromUtf8("New connection!"));
QTcpSocket* clientSocket=tcpServer->nextPendingConnection();
int idusersocs=clientSocket->socketDescriptor();
SClients[idusersocs]=clientSocket;
connect(SClients[idusersocs],SIGNAL(readyRead()),this, SLOT(slotReadClient()));
}
}
And for client:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
socket = new QTcpSocket(this);
socket->connectToHost("95.220.162.117", 33333);
socket->waitForConnected();
}
MainWindow::~MainWindow()
{
delete ui;
}
I am a novice in the field of working with network, so please explain me what I am doing wrong
"95.220.162.117" looks like a public European IP address. This public IP address is shared by all the computers/tablets/phones/etc. in your home/office. Think of it this way: The public IP address points to your router, not to a specific computer.
When a client sends a request to a public IP address, the router receives the request first. It is then the router's job to forward the request to the correct device... but in your case, your router doesn't know which device should receive the request!
There are two levels to making your connection work:
1. Private: Within your local network (Easier)
On your server, open your console and enter the following to find your private/local IP address:
ifconfig -a
Your local IP address is different from your public IP address. It identifies a specific computer on your local network. Make your client connect to this address, and your server should receive the request.
This only works when the client and the server are on the same local network (e.g. connected to the same router)
2. Public: Over the internet (Harder)
You need to set up Port Forwarding -- This tells your router to take requests received at port 33333 and forward them to your server.
To learn more about this topic, read up on Network Address Translation.

telnet client not connecting -- to QTCPserver

Why i am not able to connect to a server running on my localhost using telnet client ?
I am using windows-7 & telnet client is turned on in control panel.
Please suggest how to make it working ?
#define SERVER_PORT 5000
Tcp server is created in the tcpserver object :---
tcpserverobject::tcpserverobject(QObject *parent) :
QObject(parent), tcpServer(0)
{
tcpServer = new QTcpServer;
connect(tcpServer, SIGNAL(newConnection()), this, SLOT(on_newConnection()));
}
// Common slot for the tcpserver - thread
void tcpserverobject::dowork()
{
if (!tcpServer->listen(QHostAddress::LocalHost, SERVER_PORT )) {
qDebug() << "\n returning from server listning error .. !!! ";
return;
}
qDebug() << "\n server listning";
//while(1)
while(!m_bQuit)
{
}
}
Server new connection code :---
void tcpserverobject::on_newConnection()
{
QByteArray block;
block.append(" \n Hello from server .. !!!") ;
QTcpSocket *clientConnection = tcpServer->nextPendingConnection();
connect(clientConnection, SIGNAL(disconnected()),
clientConnection, SLOT(deleteLater()));
// Create new thread for this .. client request ..!!
qDebug() << "\n New connection request ..!!!";
qDebug() << "\n New client from:" << clientConnection->peerAddress().toString();
clientConnection->write(block);
clientConnection->flush();
clientConnection->disconnectFromHost();
qDebug() << "\n New connection request closed ..!!!";
}
Now i enter command in telnet :----
C:\Users\Admin> telnet
Welcome to Microsoft Telnet Client
Escape Character is 'CTRL+]'
Microsoft Telnet> open localhost 5000
Connecting To localhost...
I am able to make my server go in listen mode, as following statement is printed :--
qDebug() << "\n server listning";
But why telnet client is not able to connect to the server running on localhost & PORT = 5000 ?
In the function do work, you have this code: -
//while(1)
while(!m_bQuit)
{
}
This is going to stop the current thread from processing messages. If you want to be able to stop the server, have a slot, in the tcpserverobject class, which will close the connection to the QTcpServer when it receives a signal.

How a client app connect to an SSL server with a self-signed certificate in Qt?

I want to communicate with a POP3 server with ssl and port 995 with my client app
the certificate of server is self-signed and while running the app the error that received is:
The certificate is self-signed, and untrusted
A part of code is:
socket = new QSslSocket(this);
QFile certfile("D:\\hani\\cert\\localhost.localdomain.pem");
Q_ASSERT(certfile.open(QIODevice::ReadOnly));
QList<QSslCertificate> certList;
QSslCertificate cert(&certfile,QSsl::Pem);
certList.append(cert);
socket->addCaCertificate(cert);
socket->setCaCertificates(certList);
QList<QSslCertificate> serverCert = socket->caCertificates();
What can I do?
DO NOT, let me repeat, DO NOT call ignoreSslErrors(). It completely defeats the purpose of SSL/TLS. There are very special cases where it can be called safely, but this (self-signed certificate) is not a special case.
The following minimal code, ready to run, shows how to securely accept a server self-signed certificate. Do not shortcut it.
The driver:
int main(int argc, char** argv) {
QCoreApplication app(argc, argv);
QTextStream log(stdout);
DummyClient dummy(log);
QObject::connect(&dummy, SIGNAL(done()), &app, SLOT(quit()));
return app.exec();
}
The DummyClient class:
/*
* Show how to safely authenticate a TLS server which uses a self-signed certificate.
* Warning: No error handling to keep the code short.
*/
class DummyClient : public QObject {
Q_OBJECT
public:
DummyClient(QTextStream& log)
: _log(log),
_sock(new QSslSocket(this)) {
connect(_sock, SIGNAL(encrypted()), this, SLOT(onEncrypted()));
connect(_sock, SIGNAL(sslErrors(QList<QSslError>)),
this, SLOT(onSslErrors(QList<QSslError>)));
connect(_sock, SIGNAL(error(QAbstractSocket::SocketError)),
this, SLOT(onErrors(QAbstractSocket::SocketError)));
// Trust store: which CAs or self-signed certs we are going to trust.
//
// We use setCaCertificates() instead than QSslSocket::addCaCertificates()
// because we don't want to trust the ~200 default CAs.
QList<QSslCertificate> trustedCas = QSslCertificate::fromPath("server-cert.pem");
if (trustedCas.empty()) {
qFatal("Error: no trusted Cas");
}
_sock->setCaCertificates(trustedCas);
bool mutualAuth = false;
if (mutualAuth) {
// Our identity
_sock->setPrivateKey("client-key.pem");
_sock->setLocalCertificate("client-cert.pem");
}
_log << "Connecting" << endl;
// Note: serverName must match the cert CN or alternative name.
Qstring serverName = "myserver.example.org";
_sock->connectToHostEncrypted(serverName, 995);
}
signals:
void done();
private slots:
void onEncrypted() {
_log << "onEncrypted" << endl;
/* Everything is good. Start communicating. */
emit done();
}
void onSslErrors(QList<QSslError> errors) {
QSslError first = errors.takeFirst();
_log << "onSslErrors: " << first.errorString() << endl;
/* Something went wrong in the TLS handshake. Inform the user and quit! */
emit done();
}
void onErrors(QAbstractSocket::SocketError) {
_log << "onErrors: " << _sock->errorString() << endl;
emit done();
}
private:
QTextStream& _log;
QSslSocket* _sock;
};
http://qt-project.org/doc/qt-5.1/qtnetwork/qsslsocket.html
Look at the description of QSslSocket::sslErrors:
If you want to continue connecting despite the errors that have occurred,
you must call QSslSocket::ignoreSslErrors() from inside a slot connected
to this signal.
DISCLAIMER: This is very ill-advised, as it leaves the server "wide open" to man-in-the-middle attacks

Resources