我试图在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!");
}