qt tcp connection under linux

858 views Asked by At

I'm trying to create a client-server application on QT. I have no problems with algorithms. QT is fine. Everything works fine, but only under Windows. When running the application under Linux, the client successfully connects to the server and successfully writes data socket->write(myDataArray) = myDataArray.length(), but the server does not process the readyRead signal. This problem occurs only under Linux. Does anyone have any ideas of what is going on? I use Ubuntu 14.04 and Windows 7, qt version 5.3.2.


client code:

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

enum CONNECTION_TYPE{
    SSL_CONNECTION = 0,
    TCP_CONNECTION = 1
};

ClientMainWindow::ClientMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->socket = NULL;
    socketType = SSL_CONNECTION;
    msgI = 0;
}

ClientMainWindow::~ClientMainWindow()
{
    delete ui;
}

QAbstractSocket* ClientMainWindow::getSocket()
{
    bool wasError = false;
    QAbstractSocket *socket;
    if (SSL_CONNECTION == this->socketType)
    {
        QString keyFileName = "baseEnicsKey.key";
        QString certificateFileName =  "baseEnicsCertificate.csr";
        QSsl::KeyAlgorithm algorithm = QSsl::Rsa;
        QSsl::EncodingFormat encodingFormat = QSsl::Pem;
        QByteArray passPhrase = "pass0";

        QSslSocket *sslSocket = new QSslSocket(this);


        QByteArray  key;
        QFile  fileKey(keyFileName);
        if(fileKey.open(QIODevice ::ReadOnly))
        {
           key = fileKey.readAll();
           fileKey.close();
        }
        else
        {
            wasError = true;
            qDebug() << fileKey.errorString();
        }

        QSslKey sslKey(key, algorithm, encodingFormat, QSsl::PrivateKey, passPhrase);
        sslSocket->setPrivateKey(sslKey);


        QByteArray  certificate;
        QFile  fileCertificate(certificateFileName);
        if(fileCertificate.open(QIODevice ::ReadOnly))
        {
           certificate = fileCertificate.readAll();
           fileCertificate.close();
        }else
        {
           qDebug() << fileCertificate.errorString()
                    << fileCertificate.fileName();
           wasError = true;
        }
        if(!wasError){
            QSslCertificate sslCertificate;
            sslCertificate = QSslCertificate(certificate);

            sslSocket->addCaCertificate(sslCertificate);
            sslSocket->setLocalCertificate(sslCertificate);

            QList<QSslCertificate> sslCertificates;
            sslCertificates.append(sslCertificate);
            sslSocket->setDefaultCaCertificates(sslCertificates);

            sslSocket->setPeerVerifyMode(QSslSocket::VerifyPeer);
            sslSocket->setProtocol(QSsl::SslV3);
            socket = sslSocket;         
        }
        else{
            socket = NULL;
        }
    }
    else
    {
        socket = new QTcpSocket();   
    }
    return socket;
}

void ClientMainWindow::readyReadSlot()
{
    QDataStream in(this->socket);
    in.setVersion(QDataStream::Qt_5_0);
    quint32 blockSize = 0;
    qDebug() << "Client::readData";
    if (this->socket->bytesAvailable() >= (int)sizeof(quint32))
    {
        in >> blockSize;
        if (this->socket->bytesAvailable() >= blockSize)
        {
            QByteArray b;
            in >> b;
            qDebug() << "from client :"<< b;
        }
        else
        {
            qDebug() << "error : this->tcpSocket->bytesAvailable() < blockSize";
        }
    }
    else
    {
        qDebug() << "error : this->tcpSocket->bytesAvailable() < (int)sizeof(quint32)\n";
    }

}


void ClientMainWindow::newDataForWriteSlot(QByteArray b)
{
    b.append("--");
    b.append(QString::number(msgI));
    msgI++;
    qDebug() << "newDataForWriteSlot: " << b;
    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);
    out.setVersion(QDataStream::Qt_5_0);
    out << (quint32)0;
    out << b;
    out.device()->seek(0);
    out << (quint32)(block.size() - sizeof(quint32));
    qDebug() << "block length" << block.length();
    qDebug() << "write length"<< this->socket->write(block);
    this->socket->flush();
}

void ClientMainWindow::sslErrorSlot(QList<QSslError> error)
{
    qDebug() << "sslErrorSlot: " << error;
    ((QSslSocket*)this->socket)->ignoreSslErrors();
}

void ClientMainWindow::socketErrorSlot(QAbstractSocket::SocketError error)
{
    qDebug() << "socketErrorSlot: " << error;
}

void ClientMainWindow::isEncryptionReadySlot()
{
    qDebug() << "isEncryptionReadySlot";
}

void ClientMainWindow::isConnectedSlot()
{
    qDebug() << "isConnectedSlot";
}

void ClientMainWindow::encryptedBytesWrittenSlot(qint64 x)
{
    qDebug() << "encryptedBytesWrittenSlot: " << x;
}

void ClientMainWindow::connectToServer()
{
    delete this->socket;
    this->socket = getSocket();

    if (SSL_CONNECTION == this->socketType)
    {

        connect(((QSslSocket*)this->socket), SIGNAL(sslErrors(QList<QSslError>)),
                this, SLOT(sslErrorSlot(QList<QSslError>))
        );
        connect(((QSslSocket*)this->socket), SIGNAL(encryptedBytesWritten(qint64)),
                this, SLOT(encryptedBytesWrittenSlot(qint64))
        );
    }
    connect(this->socket, SIGNAL(connected()),
            this, SLOT(isConnectedSlot()));
    connect(this->socket, SIGNAL(readyRead()),
            this, SLOT(readyReadSlot())
    );
    connect(this, SIGNAL(newDataForWriteSignal(QByteArray)),
            this, SLOT(newDataForWriteSlot(QByteArray))
    );
    connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(socketErrorSlot(QAbstractSocket::SocketError))
    );
    QString hostName = "127.0.0.1";
    int port = 9600;
    if (SSL_CONNECTION == this->socketType)
    {
        ((QSslSocket*)this->socket)->connectToHostEncrypted(
                    hostName,
                    port,
                    QSslSocket::ReadWrite,
                    QSslSocket::IPv4Protocol);
    }
    else
    {
        this->socket->connectToHost(
                    hostName, 
                    port,
                    QSslSocket::ReadWrite,
                    QSslSocket::IPv4Protocol);    
    }
    if(!this->socket->waitForConnected())
    {
        qDebug() << "connection time out";    
    }
    this->newDataForWriteSlot("Hi I'm Client. It's my first connection.");
}

void ClientMainWindow::on_pushButton_clicked()
{
    this->socketType = SSL_CONNECTION;
    this->connectToServer();
}

void ClientMainWindow::on_pushButton_2_clicked()
{
    this->socketType = TCP_CONNECTION;
    this->connectToServer();
}

void ClientMainWindow::on_pushButton_3_clicked()
{
    this->newDataForWriteSlot("hi, i'm client!");
}

Server code:

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

enum CONNECTION_TYPE{
    SSL_CONNECTION = 0,
    TCP_CONNECTION = 1
};


ServerMainWindow::ServerMainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    this->server = new QTcpServer();
    connect(this->server, SIGNAL(newConnection()),
            this, SLOT(incomingConnectionSlot()));
    connect(this->server, SIGNAL(acceptError(QAbstractSocket::SocketError)),
            this, SLOT(serverErrorSlot(QAbstractSocket::SocketError))
            );
    QHostAddress adress;
    adress.setAddress("127.0.0.1");
    int port = 9600;

    this->socketType = SSL_CONNECTION;
    this->socket = NULL;
    if (!this->server->listen(adress, port))
    {
        qDebug() << "Server could not start";
    }
    msgI = 0 ;
}

ServerMainWindow::~ServerMainWindow()
{
    delete ui;
}

void ServerMainWindow::incomingConnectionSlot()
{

    disconnect(this->socket, SIGNAL(readyRead()),
            this, SLOT(readyReadSlot()));
    disconnect(this, SIGNAL(newDataForWriteSignal(QByteArray)),
            this, SLOT(newDataForWriteSlot(QByteArray))
            );
    disconnect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(socketErrorSlot(QAbstractSocket::SocketError))
            );
    if (SSL_CONNECTION == socketType)
    {
        disconnect(((QSslSocket*)this->socket), SIGNAL(peerVerifyError(QSslError)),
                this, SLOT(peerVerrefyErrorSlot(QSslError))
                );
        disconnect(((QSslSocket*)this->socket), SIGNAL(encrypted()),
                this, SLOT(isEncryptionReadySlot())
                );
        disconnect(((QSslSocket*)this->socket), SIGNAL(encryptedBytesWritten(qint64)),
                   this, SLOT(encryptedDataWriteSlot(qint64)));
    }

    delete this->socket;
    this->socket = this->getSocket();

    this->incomingConnection(
                this->server->nextPendingConnection()->socketDescriptor());

    connect(this->socket, SIGNAL(readyRead()),
            this, SLOT(readyReadSlot())
            );

    connect(this->socket, SIGNAL(error(QAbstractSocket::SocketError)),
            this, SLOT(socketErrorSlot(QAbstractSocket::SocketError))
            );
    if (SSL_CONNECTION == socketType)
    {
        connect(((QSslSocket*)this->socket), SIGNAL(encrypted()),
            this, SLOT(isEncryptionReadySlot())
            );
        connect(((QSslSocket*)this->socket), SIGNAL(peerVerifyError(QSslError)),
                this, SLOT(peerVerrefyErrorSlot(QSslError))
                );
        connect(((QSslSocket*)this->socket), SIGNAL(encryptedBytesWritten(qint64)),
                   this, SLOT(encryptedDataWriteSlot(qint64)));
        ((QSslSocket*)this->socket)->startServerEncryption();
    }
    qDebug() << "is socket open" << this->socket->isOpen();
    this->newDataForWriteSlot("Hi I'm Server! It's my first connection!");

}

void ServerMainWindow::incomingConnection(qintptr socketDescriptor)
{
    qDebug() << "incomingConnection" << socketDescriptor;
    this->socket->setSocketDescriptor(socketDescriptor);
}

QAbstractSocket* ServerMainWindow::getSocket()
{
    bool wasError = false;
    QAbstractSocket *socket;
    if (SSL_CONNECTION == this->socketType)
    {
        QString keyFileName = "baseEnicsKey.key";
        QString certificateFileName =  "baseEnicsCertificate.csr";
        QSsl::KeyAlgorithm algorithm = QSsl::Rsa;
        QSsl::EncodingFormat encodingFormat = QSsl::Pem;
        QByteArray passPhrase = "pass0";

        QSslSocket *sslSocket = new QSslSocket(this);


        QByteArray  key;
        QFile  fileKey(keyFileName);
        if(fileKey.open(QIODevice ::ReadOnly))
        {
           key = fileKey.readAll();
           fileKey.close();
        }
        else
        {
            wasError = true;
            qDebug() << fileKey.errorString();
        }

        QSslKey sslKey(key, algorithm, encodingFormat, QSsl::PrivateKey, passPhrase);
        sslSocket->setPrivateKey(sslKey);


        QByteArray  certificate;
        QFile  fileCertificate(certificateFileName);
        if(fileCertificate.open(QIODevice ::ReadOnly))
        {
           certificate = fileCertificate.readAll();
           fileCertificate.close();
        }else
        {
           qDebug() << fileCertificate.errorString()
                    << fileCertificate.fileName();
           wasError = true;
        }
        if(!wasError){
            QSslCertificate sslCertificate;
            sslCertificate = QSslCertificate(certificate);

            sslSocket->addCaCertificate(sslCertificate);
            sslSocket->setLocalCertificate(sslCertificate);

            QList<QSslCertificate> sslCertificates;
            sslCertificates.append(sslCertificate);
            sslSocket->setDefaultCaCertificates(sslCertificates);

            sslSocket->setPeerVerifyMode(QSslSocket::QueryPeer);
            sslSocket->setProtocol(QSsl::SslV3);
            socket = sslSocket;
        }
        else{
            socket = NULL;
        }
    }
    else
    {
        socket = new QTcpSocket();        
    }
    return socket;
}

void ServerMainWindow::readyReadSlot()
{
    QDataStream in(this->socket);
    in.setVersion(QDataStream::Qt_5_0);
    quint32 blockSize = 0;
    qDebug() << "Server::readData";
    if (this->socket->bytesAvailable() >= sizeof(quint32))
    {
        in >> blockSize;
        qDebug() << "this->socket->bytesAvailable" << this->socket->bytesAvailable();
        if (this->socket->bytesAvailable() >= blockSize)
        {
            QByteArray b;
            in >> b;
            qDebug() << "from client: " << b;
        }
        else
        {
            qDebug() << "error : this->tcpSocket->bytesAvailable() < blockSize";
            QByteArray b;
            in >> b;
            qDebug() << b;
        }
    }
    else
    {
        qDebug() << "error : this->tcpSocket->bytesAvailable() < (int)sizeof(quint32)";
    }

}


void ServerMainWindow::newDataForWriteSlot(QByteArray b)
{
    b.append("--");
    b.append(QString::number(msgI));
    msgI++;
    qDebug() << "newDataForWriteSlot: "<< b;

    QByteArray block;
    QDataStream out(&block, QIODevice::WriteOnly);

    out.setVersion(QDataStream::Qt_5_0);
    out << (quint32)0;
    out << b;
    out.device()->seek(0);
    out << (quint32)(block.size() - sizeof(quint32));
    qDebug() << "block length" << block.length();
    qDebug() << "write length"<< this->socket->write(block);
    this->socket->flush();
}

void ServerMainWindow::peerVerrefyErrorSlot(QSslError error)
{
    qDebug() << "peerVerrefyErrorSlot: " << error;
}

void ServerMainWindow::socketErrorSlot(QAbstractSocket::SocketError error)
{
    qDebug() << "socketErrorSlot: " << error;
}

void ServerMainWindow::isEncryptionReadySlot()
{
    qDebug() << "isEncryptionReadySlot";
}


void ServerMainWindow::serverErrorSlot(QAbstractSocket::SocketError error)
{
    qDebug() << "serverErrorSlot: " << error;
}


void ServerMainWindow::on_checkBox_clicked()
{
    if(ui->checkBox->isChecked())
    {
        this->socketType = SSL_CONNECTION;    
    }
    else
    {
        this->socketType = TCP_CONNECTION; 
    }
}

void ServerMainWindow::encryptedDataWriteSlot(qint64 x)
{
    qDebug() << "encryptedDataWrite" << x;
}

void ServerMainWindow::on_writeButton_clicked()
{
    this->newDataForWriteSlot("I'm server!");
}
0

There are 0 answers