编辑:您的错误是您以只读out
模式打开数据流,但尝试将接收到的字节数组写入其中:
void Server::readyRead()
{
QByteArray block;
QDataStream out(&block, QIODevice::ReadOnly); // !mistake, WriteOnly mode is needed
out << tcpSocket->readAll(); // this is write operation
//...
}
附加:请注意,Qt 数据类型的序列化机制在这种情况下很有用:
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