我是Qt的新手,现在还有点挣扎。我正在尝试使用QTcpSocket将字符串从客户端发送到服务器。
客户端:
QByteArray block;
QDataStream out(&block, QIODevice::WriteOnly);
out.setVersion(QDataStream::Qt_4_0);
out << name;
tSock->connectToHost(ipAddress, portNumb.toInt());
tSock->waitForConnected();
tSock->write(block); // block is not empty
tSock->flush();服务器端:
void Server::readyRead()
{
QByteArray block;
QDataStream out(&block, QIODevice::ReadOnly);
out << tcpSocket->readAll();
QString name(block); // block is empty
players.insert(name, tcpSocket);
std::cout << "name: " << name.toStdString(); // TODO remove
}在服务器端,程序在收到数据时进入readyRead(),但是块是空的,尽管在客户端调用tSock->write(block)时块不是空的……问题似乎出在哪里?如果有任何帮助,我将不胜感激。谢谢!
发布于 2017-06-14 03:08:38
编辑:您的错误在于您在ReadOnly模式下打开了out数据流,但尝试将接收到的字节数组写入:
void Server::readyRead()
{
QByteArray block;
QDataStream out(&block, QIODevice::ReadOnly); // !mistake, WriteOnly mode is needed
out << tcpSocket->readAll(); // this is write operation
//...
}Additional:请注意,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 signal上你会收到发送的完整包裹。因此,请参见下面的示例。
需要注意的是,在实际情况下(当客户-服务器通信中有几个不同的数据包,并且不知道您收到的几个可能的包是哪种类型),通常会使用更复杂的算法,因为在通信中readyRead事件可能会出现以下情况:
完整的packet received
的一部分
算法的变体(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
发布于 2017-06-14 21:38:41
您的服务器似乎没有足够的时间从客户端写入数据。请试试这个..
tcpsocket->waitForBytesWritten(1000);发布于 2017-06-14 22:06:53
readyRead代码错误地填写了block。您还假设您将读取足够的数据来传达整个字符串。这永远不会得到保证。当readyRead触发它时,你所知道的就是至少有一个字节需要读取。QDataStream事务系统有助于实现这一点。
这将是一个正确的实现:
class Server : public QObject {
Q_OBJECT
QPointer<QTcpSocket> m_socket;
QDataStream m_in{m_socket.data(), &QIODevice::ReadOnly};
void onReadyRead();
public:
Server(QTcpSocket * socket, QObject * parent = {}) :
QObject(parent),
m_socket(socket)
{
connect(socket, &QIODevice::readyRead, this, &Server::onReadyRead);
}
}
void onReadyRead() {
while (true) { // must keep reading as long as names are available
QString name;
in >> name;
if (in.commitTransaction()) {
qDebug << name;
players.insert(name, &m_socket.data());
} else
break;
}
};https://stackoverflow.com/questions/44527759
复制相似问题