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跨线程调用(官方推荐方法,非百度烂大街方法)