0

I'm trying to make client and server using QTcpSocket and QTcpServer.

So, what happens to server.

  1. I run the server, it starts listening (successfully [checked by myself])
  2. I run client, enter 127.0.0.1 for IP address and 30000 for port
  3. Client says that connection estabilished
  4. Server doesn't do anything, just keep waiting

Parts of my program:

//server-work.h
#ifndef SERVERWORK_H
#define SERVERWORK_H

#include <QtCore>
#include <QSqlError>
#include <QDebug>
#include <QSqlQuery>
#include <unistd.h>
#include <QtNetwork/QTcpServer>
#include <QtNetwork/QTcpSocket>
#include <QtSql/QSqlDatabase>
#include "lssclient.h"
class LSSClient;

class LTcpServer : public QTcpServer
{
    Q_OBJECT
public:

    class LTWorkWithClients : public QThread
    {
        //Q_OBJECT
    public:
        LTcpServer* server;
        LTWorkWithClients(QObject* parent = 0, LTcpServer *server = 0):
            QThread(parent)
        {
            this->server = server;
        }

    protected:
        void run() {
            qDebug() << "started";
            server->workWithIncomingConnection();
        }
    };

    QSqlDatabase db; // clients in database

    LTWorkWithClients* t_workWithClients;
    QQueue<quintptr> clientsToBeAttached;
    QList<LSSClient*> clients;

    LResult workWithIncomingConnection  ();

    LResult serverInit          ();
    LResult createDatabase      ();

    static QTextStream& qStdout ();

    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;

protected:

private:

};

#endif // SERVERWORK_H

I know that this nested thread class is strongly wrong way to do this thing, but i don't have much time to do it correctly

// server-work.cpp [PART]
LResult LTcpServer::serverInit()
{
    checkError;
    db = QSqlDatabase::addDatabase("QSQLITE");
    db.setDatabaseName("serverDB");

    if (!db.open()) {
        qDebug() << "Error opening database...";
        qDebug() << db.lastError().text();
        return LVError;
    } else {
        qDebug() << "Database successfully opened";
    }
    if(!this->listen(QHostAddress::Any, 30000)){
        qDebug() << "Error starting listening...";
        return LVError;
    } else {
        qDebug() << "Start listening successfully";
    }
    t_workWithClients = new LTWorkWithClients(this, this);
    t_workWithClients->start();
    return LVSuccess;
}

void LTcpServer::incomingConnection(qintptr socketDescriptor)
{
    qDebug() << Q_FUNC_INFO << " new connection";
    clientsToBeAttached.enqueue(socketDescriptor);
    qDebug() << "here1";
}

LResult LTcpServer::workWithIncomingConnection()
{
    bool toExit = false;
    while (!toExit) {
        checkError;
        qDebug() << "1";
        if (clientsToBeAttached.length() != 0) {
            quintptr eachClientDescriptor = clientsToBeAttached.dequeue();
            qDebug() << "2";
            LSSClient* client = new LSSClient(this);
            client->server = this;
            client->socket->setSocketDescriptor(eachClientDescriptor);
            qDebug() << "3";
            client->registered = false;
            client->server = this;
            qDebug() << client->socket->localAddress();
            connect(client->socket, SIGNAL(readyRead()), client, SLOT(onSokReadyRead()));
            connect(client->socket, SIGNAL(connected()), client, SLOT(onSokConnected()));
            connect(client->socket, SIGNAL(disconnected()), client, SLOT(onSokDisconnected()));
            connect(client->socket, SIGNAL(error(QAbstractSocket::SocketError)),client, SLOT(onSokDisplayError(QAbstractSocket::SocketError)));
            clients.append(client);
        }
        usleep(1000000);
    }
    return LVSuccess;
}

So, server just keep writing 1 (nothing more) every second, but client says that it is connected to the server.

  • 1
    I'd say that first you should get it working without any extra threads. Only when it works in the main thread, you should move the object to a `QThread` (you don't need to derive from `QThread`). – Kuba hasn't forgotten Monica Aug 22 '16 at 19:14
  • I can see `serverInit` is where you are creating the thread, you are not calling it anywhere here. – Mike Aug 22 '16 at 20:22
  • if you want to have a separate thread to handle your connections, you are really doing wrong. here are some issues with your current design: 1) `clientsToBeAttached`, `server` are used in both threads without any synchronization mechanism. 2) you are polling every 1 second to check if there are any new connected clients in the queue. This is a typical example of a producer/consumer problem. take a look at how this is done in Qt [here](http://doc.qt.io/qt-5/qtcore-threads-waitconditions-example.html) and [here](http://doc.qt.io/qt-5/qtcore-threads-semaphores-example.html). – Mike Aug 22 '16 at 20:41
  • but it would be better for you to read the [Qt Threaded Fortune Example](https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html) to avoid threading problems. Also, are you sure you want to go multithreaded? why not run everything in your GUI thread? – Mike Aug 22 '16 at 20:44
  • The problem is that incomingConnecion not firing (no qdebug message). I can't see sence of doing threads fight way before I understand why incomingConnecion not firing... Also, i tried to use newConnection(without passing to other thread), it also wasn't firing ... thanks for eз links, but i already have seen fortune example @Mike – Леонид Мащенко Aug 23 '16 at 04:47
  • @Kuba Ober, look onto my preivious comment – Леонид Мащенко Aug 23 '16 at 04:48
  • @Mike it's planed as big project starting from learning some Qt – Леонид Мащенко Aug 23 '16 at 04:52

1 Answers1

0

This structure might help...

in your ltcpserver.h file:

class LTcpServer : public QTcpServer
{
    Q_OBJECT
public:
    explicit LTcpServer(QObject * parent = 0);
    void incomingConnection(qintptr socketDescriptor) Q_DECL_OVERRIDE;
private:
    QThread *myThread;
};

and in your ltcpserver.cpp:

LTcpServer::LTcpServer(QObject * parent) : QTcpServer(parent)
{
    if(this->listen(QHostAddress::Any,30000))
    {
        qDebug() << "server started...";
    }
    else
    {
        qDebug() << "server could not be started...";
    }
    myThread = new QThread();
    myThread->start();
}

void LTcpServer::incomingConnection(qintptr socketDescriptor)
{
    LSSClient * yourClient = new LSSClient(socketDescriptor);
    yourClient->moveToThread(myThread);
    clients->append(yourClient);
}

and in your lssclient.h

class LSSClient: public QObject
{
    Q_OBJECT
public:
    explicit LSSClient(qintptr socketDescriptor,QObject * parent = 0);
private:
    void setupSocket(qintptr socketDescriptor);
    QTcpSocket * socket;
public slots:
    void readyRead();
    void disconnected();
};

and in your lssclient.cpp

LSSClient::LSSClient(qintptr socketDescriptor,QObject * parent) : QObject(parent)
{
    setupSocket(qintptr socketDescriptor);
}

void LSSClient::setupSocket(qintptr socketDescriptor)
{
    socket = new QTcpSocket(this);
    socket->setSocketDescriptor(sDescriptor);
    connect(socket,SIGNAL(readyRead()),this,SLOT(readyRead()));
    connect(socket,SIGNAL(disconnected()),this,SLOT(disconnected()));
}

void LSSClient::readyRead()
{
    // do whatever you want here with incoming data
}

void LSSClient::disconnected()
{
    // do what happens to client when disconnected
}
mostafaTmj
  • 363
  • 4
  • 12