Results 1 to 7 of 7

Thread: Multiple clients and one server using QTcpServer

  1. #1
    Join Date
    Mar 2019
    Posts
    4
    Thanks
    1
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Exclamation Multiple clients and one server using QTcpServer

    Hello everyone,
    This is my first post.and i am new in Qt programming. I wrote a QT GUI program which send files from client to server through QTcpServer and QTcpSocket..I need to modified my code to multiple clients..I tried multi-threading ,,but thread crashed.Is multi-threading only way to handle it?..or can I use any other method?

  2. #2
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,249
    Thanks
    36
    Thanked 1,508 Times in 1,459 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multiple clients and one server using QTcpServer

    You don't need multi-threading, Qt can handle multiple connections in parallel as long as you are using event driven I/O.

    Each client connection will result in an emit of the newConnection() signal of QTcpServer, you can then handle each socket from nextPendingConnection() the same way.

    Cheers,
    _

  3. The following user says thank you to anda_skoa for this useful post:

    deby25 (3rd April 2019)

  4. #3
    Join Date
    Mar 2019
    Posts
    4
    Thanks
    1
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multiple clients and one server using QTcpServer

    Thanks..please give me example or link for multiple client without multi thread..

  5. #4
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,249
    Thanks
    36
    Thanked 1,508 Times in 1,459 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multiple clients and one server using QTcpServer

    I suggest you post the code you currently have for handling one client.

    Much easier to discuss change than to create some example that then does not relate to your code at all.

    Cheers,
    _

  6. #5
    Join Date
    Mar 2019
    Posts
    4
    Thanks
    1
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multiple clients and one server using QTcpServer

    Yes Sir,
    I am sending my code..both server and client...If Client send text file ,Then code is working fine..but there is problem with pdf file,image file other than text file,..There is problem with the size difference with the file send and receive.my client is Qt-widget and Server is Qt-console.
    // myserver.h

    #ifndef MYSERVER_H
    #define MYSERVER_H

    #include <QTcpServer>
    #include "mythread.h"

    #define CLIENT_FILE "/home/User1/ClientFile/"

    class MyServer : public QTcpServer
    {
    Q_OBJECT
    public:
    explicit MyServer(QObject *parent = 0);
    ~MyServer();

    void startServer();
    signals:

    public slots:
    private:
    int server_status;

    QTcpServer *tcpServer;
    // QTcpSocket *tcpServerConnection;



    protected:
    void incomingConnection(qintptr socketDescriptor);

    };

    #endif // MYSERVER_H


    // mythread.h

    #ifndef MYTHREAD_H
    #define MYTHREAD_H

    #include <QThread>
    #include <QTcpSocket>
    #include <QDebug>

    #include <QtNetwork>
    #include <QTcpSocket>
    #include <QObject>
    #include <QByteArray>
    #include <QDebug>

    #include <QFile>
    #include <QString>
    #include <QTextStream>
    #include <QIODevice>

    #include <QDir>
    #include <QTextCodec>

    #define CLIENT_FILE "/home/User1/ClientFile/"


    class MyThread : public QThread
    {
    Q_OBJECT
    public:
    explicit MyThread(qintptr ID, QObject *parent = 0);

    void run();

    signals:
    void error(QTcpSocket::SocketError socketerror);

    public slots:
    //void readyRead();
    void disconnected();


    private slots:

    void acceptConnection();
    void slotReadClient();


    private:

    QTcpServer *tcpServer;
    QTcpSocket *tcpServerConnection;

    qintptr socketDescriptor;


    QTcpSocket *m_socket;
    QString fileName;
    QString fileSize;
    //QListWidget *showWidget;
    //QGridLayout *layout;
    bool isInfoGot = false;
    int server_status;

    qint32 realFileSize;
    void sendMessage(int code);


    };

    #endif // MYTHREAD_H


    // myserver.cpp

    #include "myserver.h"
    #include "mythread.h"

    #define CLIENT_PORT 33333
    #define SERVER_PORT 44444

    MyServer::MyServer(QObject *parent) :
    QTcpServer(parent)
    {
    }
    MyServer::~MyServer()
    {
    server_status=0;
    }

    void MyServer::startServer()
    {

    if (!this->listen(QHostAddress::Any, SERVER_PORT) && server_status==0)


    {
    qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString());
    // printf("Server_status is:%d\n",server_status);
    }
    else
    {
    server_status=1;
    qDebug() << QString::fromUtf8("Server is running");

    }


    printf("Console start the server\n");
    }

    void MyServer::incomingConnection(qintptr socketDescriptor)
    {
    printf("MyServer::incomingConnection\n");
    qDebug() << socketDescriptor << " Thread is Connecting...";


    QDir::setCurrent(CLIENT_FILE);


    MyThread *thread = new MyThread(socketDescriptor, this);

    connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));

    thread->start();
    }







    // mythread.cpp

    #include "mythread.h"
    #include <QDir>

    #define CLIENT_FILE "/home/User1/ClientFile/"

    #define CLIENT_PORT 33333
    #define SERVER_PORT 44444

    MyThread::MyThread(qintptr ID, QObject *parent) :
    QThread(parent)
    {
    this->socketDescriptor = ID;
    //tcpServerConnection = new QTcpSocket();
    }

    void MyThread::run()
    {
    // thread starts here
    qDebug() << "MyThread::run()" << " Thread started";


    tcpServer = new QTcpServer(this);
    tcpServerConnection = new QTcpSocket();


    // set the ID
    if(!tcpServerConnection->setSocketDescriptor(this->socketDescriptor))
    {
    // something's wrong, we just emit a signal
    emit error(tcpServerConnection->error());
    return;
    }

    // connect socket and signal
    // note - Qt:irectConnection is used because it's multithreaded
    // This makes the slot to be invoked immediately, when the signal is emitted.

    //tcpServer = new QTcpServer(this);
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(acceptConnection()));
    if (!tcpServer->listen(QHostAddress::Any, SERVER_PORT) && server_status==0)
    // if (!tcpServer->listen(QHostAddress::Any, 44444) && server_status==0)


    {
    // qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString());
    printf("Server_status is:%d\n",server_status);
    }
    else
    {
    server_status=1;
    printf("Server_status is:%d\n",server_status);

    }

    connect(tcpServerConnection, SIGNAL(readyRead()), this, SLOT(slotReadClient()), Qt:irectConnection);

    connect(tcpServerConnection, SIGNAL(disconnected()), this, SLOT(disconnected()));

    // We'll have multiple clients, we want to know which is which
    qDebug() << socketDescriptor << " Client connected";

    // make this thread a loop,
    // thread will stay alive so that signal/slot to function properly
    // not dropped out in the middle when thread dies

    exec();
    }
    void MyThread::acceptConnection()
    {
    printf("MyThread::acceptConnection()\n");

    //Check the connection of Sever
    qDebug() << "MainWindow::acceptConnection()";
    qDebug() << QString::fromUtf8("Accept the connection");
    tcpServerConnection = tcpServer->nextPendingConnection();
    connect(tcpServerConnection,SIGNAL(readyRead()),th is, SLOT(slotReadClient()),Qt:irectConnection);
    // tcpServer->close();

    QDir::setCurrent(CLIENT_FILE);
    //QDir::setCurrent(/user)

    }

    void MyThread::slotReadClient()
    {

    qDebug() << "MainWindow::slotReadClient()";
    QDataStream in(tcpServerConnection);
    QByteArray tmpByteArray;

    if (!isInfoGot) {
    isInfoGot = true;
    in >> fileName;
    qDebug() << "Received File name:" <<fileName ;
    in >> fileSize;
    qDebug() <<"Received File size:" << fileSize;
    }
    /*************/
    //check Duplication of files

    QString filePath= CLIENT_FILE + fileName;

    qDebug () << "file naem is :" << filePath;

    if(QFile::exists(filePath))
    {
    //int qret;
    qDebug() << "File is alreday exist,so Overwrite the file";
    printf("File is alreday exist,so Overwrite the file\n");
    QFile::remove(filePath);


    }
    /************************/

    QFile loadedFile(fileName);

    if (loadedFile.open(QIODevice::Append))
    {
    while (tcpServerConnection->bytesAvailable())
    {
    qDebug() << "bytesAvailable:" << tcpServerConnection->bytesAvailable();
    in >> tmpByteArray;
    QString some(tmpByteArray);
    if (some=="#END")
    {
    isInfoGot = false;
    QFileInfo fileInfo(loadedFile);
    qDebug() << "loaded File size:" << loadedFile.size();
    //printf( "loaded File size=%ld \n",loadedFile.size());
    if (loadedFile.size() == fileSize.toInt())
    {
    // QMessageBox::information(this,"Informations","Suce ssfully uploaded to Server");
    qDebug() << "Success upload to Server ";
    printf( "Success upload to Server \n");

    sendMessage(1);
    //return 1;
    }
    else
    {
    // QMessageBox::warning(this,"Warning","Failed to upload the File to Server");
    qDebug() << "Fail upload to Server";

    sendMessage(0);
    //return 0;
    }

    break;
    }
    loadedFile.write(tmpByteArray);
    }
    loadedFile.close();
    }


    // get the information
    /* QByteArray Data = tcpServerConnection->readAll();

    // will write on server side window
    qDebug() << socketDescriptor << " Data in: " << Data;

    tcpServerConnection->write(Data);*/
    }
    void MyThread::sendMessage(int code)
    {

    QTcpSocket *sock = new QTcpSocket(this);

    sock->connectToHost("127.0.0.1", CLIENT_PORT);
    QDataStream out(sock);
    sock->write(QString::number(code).toUtf8().constData()) ;

    }

    void MyThread::disconnected()
    {


    qDebug() << socketDescriptor << " Disconnected";

    tcpServerConnection->deleteLater();
    exit(0);
    }






    //main.c
    #include <QCoreApplication>
    #include "myserver.h"
    #include "mythread.h"

    int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);


    MyServer server;
    server.startServer();

    return a.exec();
    }

    client code

    //client programe
    widget.cpp

    #include "widget.h"
    #include <QDir>
    #include <QFileInfo>
    #include <QDebug>
    #include <QProcess>
    #include <QAction>
    #include <QIcon>
    #include <QFileInfo>
    #include <QFileDialog>
    #include <QMessageBox>
    #include <QAbstractSocket>
    #include <QLineEdit>


    #define SERVER_FILE "/home/User1/ServerFile/"
    #define CLIENT_PORT 33330
    #define SERVER_PORT 44440

    Widget::Widget(QWidget *parent) :
    QWidget(parent)
    {


    tcpSocket = new QTcpSocket(this);


    NameLine= new QLineEdit (this);
    NameLine->setPlaceholderText("Enter The User Name");


    sendBtn = new QPushButton(this);
    sendBtn->setText("Send");

    showBtn = new QPushButton(this);
    showBtn->setText("Show");


    showWidget =new QListWidget(this);



    Glayout = new QGridLayout;

    // Glayout->addWidget(NameLabel,0,0,1,1);
    Glayout->addWidget(NameLine,0,0,1,2);
    Glayout->addWidget(showWidget,1,0,1,2);
    Glayout->addWidget(showBtn,2,0,1,1);
    Glayout->addWidget(sendBtn,2,1,1,1);

    setLayout(Glayout);

    connect(showBtn, &QPushButton::clicked, this, &Widget::fileShow);
    connect(sendBtn, &QPushButton::clicked, this, &Widget:nSend);



    }

    Widget::~Widget()
    {
    }

    void Widget::fileOpened()
    {
    qDebug() << " Widget::fileOpened() ";
    fileName = QFileDialog::getOpenFileName(this, tr("Open file"));
    QFileInfo fileInfo(fileName);
    //fileLabel->setText(fileInfo.fileName() + " : " + QString::number(fileInfo.size()));
    qDebug() << "Opening The file:" <<fileName;
    }

    void Widget:nSend()
    {

    QString UserName;

    /**********************************/
    if(NameLine->text().isEmpty())
    {
    QMessageBox::warning(this,"Warning","Please Enter the User Name");
    qDebug() << " not User Name ";


    }

    else
    {


    QString fileName1;
    if(showWidget->selectedItems().count()!=1)
    {
    QMessageBox::warning(this,"Warning","Please Select a File From List");
    return;
    }
    else
    {
    //start of Else

    QMessageBox::information(this,tr("Information"),tr ("%1 file is selected").arg(showWidget->currentItem()->text()));

    //1.Send File first
    fileName1= SERVER_FILE + showWidget->currentItem()->text();;
    qDebug() << "1.Full File Name:" << fileName ;

    //File 1:Transfer User Name as file


    QFileInfo fileInfo1(fileName);
    // fileLabel->setText(fileInfo.fileName() + " : " + QString::number(fileInfo.size()));
    qDebug() << "2.File name with Text Label:" << fileName1;

    // tcpSocket->connectToHost("172.16.5.250", CLIENT_PORT);
    tcpSocket->connectToHost("127.0.0.1", CLIENT_PORT);
    QFile file1(fileName1);
    qDebug() << "3.File open is:" << fileName1 ;

    QDataStream out1(tcpSocket);
    int size1 = 0;

    if (file1.open(QIODevice::ReadOnly))
    {
    QFileInfo fileInfo1(file1);
    QString fileName1(fileInfo1.fileName());

    out1 << fileName1;
    qDebug() << "File name is:" << fileName1;
    out1 << NameLine->text();

    // qDebug() << "username name is:" << fileName1;
    out1 << QString::number(fileInfo1.size());
    qDebug() << "File size is:" <<fileInfo1.size();

    while (!file1.atEnd())
    {
    QByteArray rawFile1;
    rawFile1 = file1.read(5000);
    //false size inc
    QFileInfo rawFileInfo1(rawFile1);
    size1 += rawFileInfo1.size();
    out1 << rawFile1;
    qDebug() << "ToSend:"<< rawFile1.size();
    }

    out1 << "#END";

    startServer();
    }



    } //End of else

    } //End of else user name
    }


    void Widget::startServer()
    {
    qDebug() << "Widget::startServer().";
    qDebug() << "waiting for reply...";
    tcpServer = new QTcpServer(this);
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(acceptReplyConnection()));
    if (!tcpServer->listen(QHostAddress::Any, SERVER_PORT))
    {

    //QMessageBox::warning(this,"Warning","Unable to start the server.");
    qDebug() << QObject::tr("Unable to start the server: %1.").arg(tcpServer->errorString());
    }
    else
    {
    QMessageBox::information(this,"Information","Serve r is connected");
    //qDebug() << QString::fromUtf8("Server is connected");
    }
    }


    void Widget::acceptReplyConnection()
    {
    qDebug() << "Widget::acceptReplyConnection()";
    qDebug() << QString::fromUtf8("Waiting for connection");
    tcpServerConnection = tcpServer->nextPendingConnection();
    connect(tcpServerConnection,SIGNAL(readyRead()),th is, SLOT(slotReadClient()));
    tcpServer->close();

    }


    void Widget::slotReadClient()
    {
    qDebug() << "Widget::slotReadClient() ";
    QDataStream in(tcpServerConnection);
    QByteArray tmpArr;
    QString tmpString;
    in << tmpArr;
    qDebug() << "bytesAvailable:" << tcpServerConnection->bytesAvailable();
    qDebug() << tmpArr;


    if (tmpString.toInt()==1)
    {
    qDebug() << "successfully uploaded to Server";
    }
    else
    {
    qDebug() << "fail to upload to server";
    }
    }

    void Widget::fileShow()
    {

    qDebug() << " Widget::fileShow() ";

    QStringList list_item;
    QDir dir(SERVER_FILE);

    //Check Whether Name is blank or not

    if(NameLine->text().isEmpty())
    {
    QMessageBox::warning(this,"Warning","Please Enter the User Name");
    qDebug() << " not User Name ";

    }

    else
    {
    if(!dir.exists())
    {
    // qDebug() << " not exists ";
    QMessageBox::warning(this,"Warning","Cant find the any files of Server path");
    // qWarning("canot find the directory");
    }
    else
    {
    // qDebug() << " It exists ";
    dir.setFilter(QDir::Files | QDir::NoSymLinks );

    QFileInfoList list=dir.entryInfoList();

    for(int i=0;i<list.size();i++)
    {
    QFileInfo fileinfo=list.at(i);
    list_item << fileinfo.fileName();


    }

    }

    showWidget->clear();
    showWidget->addItems(list_item);
    } //EnD else for user name

    }

    //widget.h
    #ifndef WIDGET_H
    #define WIDGET_H

    #include <QWidget>
    #include <QFileDialog>
    #include <QGridLayout>
    #include <QPushButton>
    #include <QDebug>
    #include <QString>
    #include <QLabel>
    #include <QNetworkAccessManager>
    #include <QTcpSocket>
    #include <QFile>
    #include <QDataStream>
    #include <QProgressBar>
    #include <QTcpServer>
    #include <QListWidget>


    namespace Ui {
    class Widget;
    }

    class Widget : public QWidget
    {
    Q_OBJECT

    public:
    Widget(QWidget *parent = 0);
    QFileDialog *fileDialog;
    QGridLayout *layout;
    QPushButton *fileBtn;
    QPushButton *sendBtn;
    QPushButton *showBtn;
    QLabel *fileLabel;
    QLabel *NameLabel;
    QLineEdit *NameLine;
    QLabel *progressLabel;
    QProgressBar *progressBar;
    QTcpServer *tcpServer;
    QTcpSocket *tcpServerConnection;

    QGridLayout *Glayout;

    QString fileName;
    QTcpSocket *tcpSocket;
    QListWidget *showWidget;

    void startServer();

    ~Widget();
    public slots:
    void fileOpened();
    void onSend();
    void acceptReplyConnection();
    void slotReadClient();
    void fileShow();
    void displayError(QAbstractSocket::SocketError socketError);
    };

    #endif // WIDGET_H

    //main.c
    #include "widget.h"
    #include <QApplication>
    #include <QLabel>
    #include<QPixmap>
    #include <QDesktopWidget>

    int main(int argc, char *argv[])
    {
    QApplication a(argc, argv);
    Widget w;
    w.setFixedWidth(300);
    w.setFixedHeight(200);
    w.show();


    return a.exec();*
    }

  7. #6
    Join Date
    Jan 2006
    Location
    Graz, Austria
    Posts
    8,249
    Thanks
    36
    Thanked 1,508 Times in 1,459 Posts
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multiple clients and one server using QTcpServer

    Ok, this definitely does not need threads on the server side, but that part seems to be reasonably done.


    Quote Originally Posted by deby25 View Post
    // myserver.h

    QTcpServer *tcpServer;
    // QTcpSocket *tcpServerConnection;
    Why is there a QTcpServer member inside the QTcpServer subclass?

    Quote Originally Posted by deby25 View Post
    // mythread.h

    #ifndef MYTHREAD_H
    #define MYTHREAD_H

    #include <QThread>
    #include <QTcpSocket>
    #include <QDebug>

    #include <QtNetwork>
    #include <QTcpSocket>
    #include <QObject>
    #include <QByteArray>
    #include <QDebug>

    #include <QFile>
    #include <QString>
    #include <QTextStream>
    #include <QIODevice>

    #include <QDir>
    #include <QTextCodec>
    Oh my, so many unnecessary includes

    Quote Originally Posted by deby25 View Post
    QTcpServer *tcpServer;
    QTcpSocket *tcpServerConnection;
    Why on earth does the client handler contain a QTcpServer?

    Quote Originally Posted by deby25 View Post
    // myserver.cpp
    That looks reasonably ok.

    Quote Originally Posted by deby25 View Post
    // mythread.cpp

    void MyThread::slotReadClient()
    {

    qDebug() << "MainWindow::slotReadClient()";
    QDataStream in(tcpServerConnection);
    QByteArray tmpByteArray;

    if (!isInfoGot) {
    isInfoGot = true;
    in >> fileName;
    You are not covering the case that there is not yet enough data for the full string.

    Quote Originally Posted by deby25 View Post
    qDebug() << "Received File name:" <<fileName ;
    in >> fileSize;
    The client writes the file name, then a user name, then the file size.
    Where are you reading the user name here?

    And again, the available data might not be sufficient enough yet.

    Quote Originally Posted by deby25 View Post
    QString some(tmpByteArray);
    if (some=="#END")
    Well, that will break if you transmit binary data or text data that contains this string.

    Totally unnecessary since you know the file size and thus know when you have read all of the file content.

    Quote Originally Posted by deby25 View Post

    void MyThread::sendMessage(int code)
    {

    QTcpSocket *sock = new QTcpSocket(this);

    sock->connectToHost("127.0.0.1", CLIENT_PORT);
    QDataStream out(sock);
    sock->write(QString::number(code).toUtf8().constData()) ;

    }
    Why don't you simply sent through the connection you already have?

    Quote Originally Posted by deby25 View Post
    // tcpSocket->connectToHost("172.16.5.250", CLIENT_PORT);
    tcpSocket->connectToHost("127.0.0.1", CLIENT_PORT);
    connectToHost() is an asynchronous operation.
    You need to connect to the socket's conncted() signal and then continue there.

    Quote Originally Posted by deby25 View Post
    out1 << NameLine->text();
    That is never read on the server side

    Quote Originally Posted by deby25 View Post
    out1 << QString::number(fileInfo1.size());
    Why send the number as a string?

    Quote Originally Posted by deby25 View Post
    QByteArray rawFile1;
    rawFile1 = file1.read(5000);
    //false size inc
    QFileInfo rawFileInfo1(rawFile1);
    You create a QFileInfo object using the 5000 bytes of file1 content as a file name?

    Quote Originally Posted by deby25 View Post
    void Widget::startServer()
    Totally unnecessary, the server can simply reply on the already established connection

    Quote Originally Posted by deby25 View Post
    void Widget::slotReadClient()
    {
    qDebug() << "Widget::slotReadClient() ";
    QDataStream in(tcpServerConnection);
    QByteArray tmpArr;
    QString tmpString;
    in << tmpArr;
    Why send an empty byte array to the server?

    Quote Originally Posted by deby25 View Post
    if (tmpString.toInt()==1)
    This will always be false because tmpString is empty.

    I would suggest the following steps

    1) Clean up the code, there are way too many commented out parts, duplicated or unnecessary includes, etc.

    2) Ensure that the data serialization and deserialization code matches. Currently the client sends three strings before the file, the server reads only two.

    3) In a slot connected to readyRead() you can't assume you are seeing a single write from the client. E.g. the client could write a block with 10 bytes, the server could received this as two blocks. you will need a bit more protocol to handle that.

    Cheers,
    _

  8. #7
    Join Date
    Mar 2019
    Posts
    4
    Thanks
    1
    Qt products
    Qt3 Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Multiple clients and one server using QTcpServer

    Thanks..i will go through my code once again according to your suggestion.

Similar Threads

  1. Replies: 8
    Last Post: 2nd December 2015, 14:52
  2. Server with multiple clients without threads
    By kernel.roy in forum Qt Programming
    Replies: 7
    Last Post: 9th September 2010, 16:37
  3. Server with multiple clients without threads
    By kernel.roy in forum Newbie
    Replies: 2
    Last Post: 9th September 2010, 04:53
  4. Replies: 7
    Last Post: 10th May 2010, 11:26
  5. Extend QTcpServer to handle multiple clients
    By DiamonDogX in forum Qt Programming
    Replies: 5
    Last Post: 24th February 2010, 19:49

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.