编辑:你的错误是你以ReadOnly模式打开out数据流,但是尝试写入接收到的字节数组给它:
void Server::readyRead()
{
QByteArray block;
QDataStream out(&block, QIODevice::ReadOnly); // !mistake, WriteOnly mode is needed
out << tcpSocket->readAll(); // this is write operation
//...
}
补充:请注意Serialization mechanism of Qt Data Types在这种情况下很有用:
tSock->write(block); // this is write just a raw data of the block, not the "QByteArray"
您可以使用流操作将必要的 Qt 数据类型直接写入套接字,而无需转换为QByteArray:
// Connect firstly
tSock->connectToHost(ipAddress, portNumb.toInt());
tSock->waitForConnected();
// Then open a data stream for the socket and write to it:
QDataStream out(tSock, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << name; // write string directly without a convertion to QByteArray
// Then you may
tSock->flush();
在客户端,然后在服务器端使用类似的流操作:
void Server::readyRead()
{
QString name;
QDataStream in(tcpSocket, QIODevice::ReadOnly /*or QIODevice::ReadWrite if necessary */);
in.setVersion(QDataStream::Qt_4_0);
in >> name; // read the string
//...
}
也可以在其他 Qt 的 i/o 设备上读取/写入对象:QFile、QSerialPort、QProcess、QBuffer 等。
编辑 2: 不能保证在 readyRead 信号上您会收到已发送的完整包裹。因此请参见下面的示例。
请注意,在实际情况下(当您在客户端-服务器通信中有几个不同的数据包,并且不知道您收到的几个可能的数据包是哪种类型时)通常有使用了更复杂的算法,因为在一次通信的readyRead事件上可能会出现以下几种情况:
- 收到完整的数据包
- 只收到了部分包裹
- 一起收到了几个包裹
算法的变体(Qt 4 Fortune Client Example):
void Client::readFortune() // on readyRead
{
QDataStream in(tcpSocket);
in.setVersion(QDataStream::Qt_4_0);
if (blockSize == 0) {
if (tcpSocket->bytesAvailable() < (int)sizeof(quint16))
return;
in >> blockSize;
}
if (tcpSocket->bytesAvailable() < blockSize)
return;
QString nextFortune;
in >> nextFortune;
//...
}
Qt 4.0 是 Qt 的太旧版本,因此另请参阅 Qt 5.9 Fortune Client Example