Qt笔记-QTcpSocket中调用readAll要注意的地方(Java中RestTemplate和Qt配合要注意的地方)

Posted IT1995

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Qt笔记-QTcpSocket中调用readAll要注意的地方(Java中RestTemplate和Qt配合要注意的地方)相关的知识,希望对你有一定的参考价值。

直接说明下我遇到的问题吧,客户端发送http协议,服务器是Qt写的,用QTcpSocket直接解析,如下HTTP

POST http://192.1.xxx.xxx:18888/XXXXX HTTP/1.1
Content-Type: application/json;charset=UTF-8
User-Agent: Java/1.8.0_181
Host: 192.1.101.189:18888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 99999

"xxxx":xxx,"xxx":"xxx","xxx":"xxx"

这里使用的是Java的RestTemplate。

服务端是这样调用的

    if(tcpSocket->waitForReadyRead(10 * 1000))
        QString msg = QString::fromUtf8(tcpSocket->readAll());
        ......
        ......
        ......
    

这样问题就来了,差不多每5次,就有1次,msg会收到:

POST http://192.1.xxx.xxx:18888/XXXXX HTTP/1.1
Content-Type: application/json;charset=UTF-8
User-Agent: Java/1.8.0_181
Host: 192.1.101.189:18888
Accept: text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2
Connection: keep-alive
Content-Length: 99999

没有body部分,这就坑了。

后面通过抓包(这里要用wireshark,使用Fiddler等web抓包是看不到现象的)等一系列测试。Java中RestTemplate这个类,有时会把http包拆分成两个(postman和一些tcp调试工具不会)。先发header以及最后的\\r\\n。再发body。

注意:这里经过大量测试不管你的数据包是多大还是多小,比如就200字节的数据包,他也会差分成2个包发,10000字节的数据,他有时只会发1个包(这里只指应用层,不讨论网卡里面的MTU和路由器包分组)。所以这里应该算是一个RestTemplate的坑。Get方法正常。

并且这个body的大小(UTF-8编码)等于Content-Length,这个是http协议规定的。所以面对这样的情况,得修改下post方法的解析。增加这样的内容:

int contentLength = DataAnaylsisTool::getHttpHeaderValue(msg, "Content-Length").toInt();
QString body = DataAnaylsisTool::getHttpBody(msg);
while(body.size() != contentLength)

	tcpSocket->waitForReadyRead();
    qint64 available = tcpSocket->bytesAvailable();
    QString bodyMsg = tcpSocket->read(available);
    body += bodyMsg;

这个getHttpHeaderValue获取了Content-Length的大小。

这个getHttpBody获取了body的内容。

通过这种方式,不管他body里面分了多少个包,都可以获取到。

以上是关于Qt笔记-QTcpSocket中调用readAll要注意的地方(Java中RestTemplate和Qt配合要注意的地方)的主要内容,如果未能解决你的问题,请参考以下文章

为啥在 Qtcpsocket 的 readyRead 回调中调用 readAll 时没有内容?

Python QtNetwork.QTcpSocket.readAll() 和 QtNetwork.QTcpSocket.write() 不起作用

Qt QTcpSocket 流式传输

Qt笔记-QTcpSocket跨线程调用(官方推荐方法,非百度烂大街方法)

Qt笔记-解决QTcpSocket发送数据成功,但接收端接收不全的问

Qt笔记-解决QTcpSocket发送数据成功,但接收端接收不全的问题