【发布时间】:2019-09-25 10:44:47
【问题描述】:
我向服务器发送请求并得到响应我的代码是这样的:
QString mywindow::SocketCommunication(QString JsonRequest)
{
QTcpSocket *socket = new QTcpSocket(this);
QString result;
socket->connectToHost(SOCKET_IP, SOCKET_PORT);//SOCKET_IP and SOCKET_PORT are defined constants and are correct
if (socket->waitForConnected(-1) && socket->state() == QAbstractSocket::ConnectedState)
{
if (socket->write(JsonRequest.toLatin1()) == -1)
{
socket->disconnectFromHost();
result = "Could not send message";
}
else
{
socket->flush();
if (!socket->waitForReadyRead(90000))
{
socket->disconnectFromHost();
result = "tcp con timeout for reading";
}
else
{
QByteArray JsonResponse = socket->readAll();// the problem is here
socket->close();
JsonResponse = JsonResponse.trimmed();
QString jsonResp = QString::fromStdString(JsonResponse.toStdString());
result = ParseResponse(jsonResp) // here i parse the response. it works fine and is not important in this question.
}
}
}
else
{
qDebug() << "cannot connect";
socket->disconnectFromHost();
result = "Could not Connect to Server";
}
return result;
}
现在,当来自服务器的响应小于 8192 字节时,它可以正常工作。否则这只读取前 8192 个字节。当我在阅读所有内容后输入socket->error() 时,我得到-1,即 QAbstractSocket::UnknownSocketError。你知道为什么会发生这种情况吗?我应该如何补救?
ps:我认为问题不在于 QAbstractSocket::DatagramTooLargeError,它是
数据报大于操作系统的限制(可以低至 8192 字节)。
因为我可以发送超过 8192 并且其他程序可以与更大的消息进行通信。
【问题讨论】:
-
多次调用阅读?无论如何,您都必须使用 TCP 来执行此操作,因为由于它是一个流式协议,因此没有包或开始或结束。一次接收可以为您提供少于一条消息、一条完整消息或多条消息。
-
你的意思是一会儿
socket->read(4096)?那这段时间应该是什么条件呢? -
多次调用读取和写入。显示的代码似乎没有完全检查
write()的返回值,因此,可能实际上并没有写出所有内容,这取决于 Qt 的 bezerkeley 套接字包装器的工作方式。 “其他程序”可以发送和接收更多内容的原因是因为它们实际上了解从套接字读取和写入的工作原理,并且可能不会读取或写入所有内容,因此它们被专门编码为具有尝试 agan 的逻辑,直到一切都完全读和写。 -
您需要在 TCP 之上提出一个协议,以某种方式告诉您需要接收多少。这可以通过使用包含要接收的数据长度的固定大小的消息头来完成,或者通过使用您检查的特定消息或“包”分隔符来完成。或者,像旧的 HTTP 一样,一直读取到连接被另一端关闭。
-
DataGram 是 UDP 概念,而不是 TCP。您需要了解 TCP 在数据包中不起作用。它是一种流式协议:你会得到一个或多个数据块,突飞猛进。您无法控制块的大小;每个都可能不同;您负责自己组装这些块(它们已正确排序)。您还需要知道数据何时通过 TCP 之外的方式完成(即提前知道多少字节或分隔符)。
标签: c++ qt qtcpsocket