linux下的qt tcp连接

时间:2014-11-14 09:09:14

标签: c++ linux qt qtcpsocket qtcpserver

我试图在QT上创建客户端 - 服务器应用程序。我对算法没有任何问题。 QT很好。一切正常,但只在Windows下。 在Linux下运行应用程序时,客户端成功连接到服务器并成功写入 data socket-> write(myDataArray)= myDataArray.length(),但服务器不处理readyRead信号。 仅在Linux下才会出现此问题。有没有人对这是怎么回事? 我使用Ubuntu 14.04和Windows 7,qt版本5.3.2。


客户代码:

#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!");
}

服务器代码:

#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 个答案:

没有答案