Nicholas Johnson
Nicholas Johnson

Reputation: 1022

QT QTcpServer not connecting in time

I am making a simple program that will 'connect' to itself and then send data. It starts a QTcpServer then waits for any incoming connections. I have a separate function that will in turn attempt to connect to this server at the localhost and port I decided on. This works when I open Telnet in the command prompt, but now in my actual program. Here is the code that I used (Some are snippets from other sources)

MainWindow.cpp:

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    server = new QTcpServer(this);
    //Initialize and start the server
    connect(server, SIGNAL(newConnection()), this, SLOT(newConnection()));
    if (!server->listen(QHostAddress::Any, 3665))
    {
        qDebug() << "Server failed to start!";
    }
    else
    {
        qDebug() << "Server started";
    }
    //Try to connect to the server
    connectToServer("127.0.0.1", qint16(3665));
}

MainWindow::~MainWindow()
{
    delete server;
    delete ui;
}

void MainWindow::connectToServer(QString host, qint16 port)
{
    qDebug() << "Connecting to " + host + " at port " + QString::number(port);
    QTcpSocket socket;
    socket.connectToHost(host, port);
    if (!socket.waitForConnected(5000))
    {
        qDebug() << socket.errorString();
    }
    while (socket.bytesAvailable() < (int)sizeof(quint16))
    {
        if (!socket.waitForReadyRead(5000))
        {
            qDebug() << socket.errorString();
        }
    }
    quint16 blockSize;
    QDataStream in(&socket);
    in.setVersion(QDataStream::Qt_5_5);
    in >> blockSize;
    while (socket.bytesAvailable() < blockSize)
    {
        if (!socket.waitForReadyRead(5000))
        {
            qDebug() << socket.errorString();
        }
    }
    QString fortune;
    in >> fortune;
    qDebug() << fortune;
}

void MainWindow::newConnection()
{
    qDebug() << "A connection has been found.";
    QTcpSocket *socket = server->nextPendingConnection();

    socket->write("hello client\r\n");
    socket->flush();
    socket->waitForBytesWritten(5000);
    socket->close();
}

Upvotes: 1

Views: 416

Answers (1)

The source of your problem is, most likely, the pseudo-synchronous mess caused by waitFor methods. Get rid of them. Furthermore, you're not guaranteed anything about how many bytes you receive upon readyRead: it's perfectly normal to receive one byte at a time, in some circumstances, or really any number of bytes, including more bytes than you might expect. Your code must cope with that.

This is one example of such approach - it does what you want, asynchronously. That is another example that shows how to leverage state machines to write asynchronous communications code using an easy to read, declarative syntax.

Upvotes: 2

Related Questions