Closed sudavida closed 2 years ago
导致数据解析失败
数据长度?结束位置?看下哪里的问题
这也可能是前面出乱码的原因
所谓的粘包问题
"tickSz":"0.0001","uly":"ZRX-USDT"}],"msg":""}
这一段,上一个请求是否已正确读出并使用?
没有,和后面的数据一起使用的
上一个请求ContentLength不对?
也有这个可能,但是读取数据还需要其他方式进行结束检查。中间是否有http协议开始,头部开始等
这块检查不应由库来操作。http返回内容完全可以再嵌套一个http报文。再做检查则无法处理这种正确的返回格式
inline Task<std::string> IConn::ReadCount (size_t _count) {
if (_count == 0)
co_return "";
std::string _tmp = "";
while (TmpData.size () < _count) {
char _buf [1024];
size_t _readed = co_await RecvImpl (_buf, sizeof (_buf));
// std::string_view { _buf, _readed }; 如果放在这里检查呢
TmpData += std::string_view { _buf, _readed };
}
_tmp = TmpData.substr (0, _count);
TmpData.erase (0, _count);
co_return _tmp;
}
“做检查则无法处理正确的返回格式”
TmpData,这里是一直暂存数据流吧,如果自己检查,正确位置截断,能不能解决问题
想要具体解决问题,首先需要调查上一个包的ContentLength对不对。如果不对,那么库无法正确处理。想要手工处理非标准HTTP报文,建议自建tcp/ssl客户端然后手工发request请求、手工解析response
如果放在response,已经在业务函数处理过程中了,多余部分也只能丢掉,可能不是合理的
while (TmpData.size () < _count) {
char _buf [1024];
size_t read_size = _count - TmpData.size ();//我改了这里
read_size = read_size>1024? 1024 : read_size;//
size_t _readed = co_await RecvImpl (_buf, read_size);//
TmpData += std::string_view { _buf, _readed };//
}
原来实际上读取数据超出了_count,如果后面有数据,就会发生错误,粘包
改了以后,有时取到的content_length会大于实际的数据长度 : 77679:77679
前面改了那个还是能够起作用,但是如果content_length大于实际数据长度的情况,还是多读取数据出来了
需确认是否因远程服务器端ContentLength不对造成。如果是,那么代表非libfv问题,将不考虑兼容这种不标准的报文
999%的情况是对的,偶尔一次实际内容长度小于Content_Length数值
如果按照Content_Length数值读数据,就会跨到了下一个报文。这个是连续大量读数据的极端情况下发生的:一个报文接着一个报文。我只能试着避免这种情况,对报文进行适当检查,补救。
好在正常报文中间不会出现类似“HTTP/**** 这种
好像没有几个像我这样做连续的大数据量访问,但确实是我的真实使用情况
改为这样试试
fv::Request::SetDefaultHeader ("Accept-Encoding", "gzip");
后面我单独试下这个,目前是没用这个。当时是出现乱码的原因,猜测是编码问题,所以取消掉了。
这个错误在gzip模式下出现: terminate called after throwing an instance of 'std::system_error' what(): cancel: Bad file descriptor
感觉是socket连接断了,但是报的错和普通模式不一样,普通模式会报:End of file之类
也可能是压缩数据格式错误
实际检查发现出现报错:catch error: internal error (SSL routines, ssl3_read_n) wrong version number (SSL routines, SSL3_GET_RECORD) 改了这里: struct SslConn: public IConn { Tcp::resolver ResolverImpl; //Ssl::context SslCtx { Ssl::context::tls }; Ssl::context SslCtx { Ssl::context::context::sslv23 };//改
改成gzip,chunked模式后还没遇到解析错误的情况
还是有结束标志比较好解析
跑出乱码: first line:����{u�F��U���H�$ثc:"оw��]yu]bu��O�jf<ɄKv�:<�.�VO�(-���Y�O�]�L�d�TPO]�ՂH�$�^�EM�H0FM@��d5�$�Aؙ�zui��_ߏ�`���zϺZ�Z,����I|�DKW�Od>�Q$X�i��f�h�y��Q$fħ�+m8^3�(&��xo�;���S�nGuu�OE��hɣm��-�����$V�ht�S7�R�9D�)���M죬'4"E�%��HZE7d�"d��→4Eb%���A��E◆]G�▒I�£:۹�)����▮��8W�─�┌/├☃F4�DK→
读http协议第一行就报错,还没进入gzip解压。导致后面跟随5-6个报文都是乱码。再后面逐渐恢复正常
这个比不使用chunked模式强,原来这种情况基本上恢复不了
也可能是linux终端缓存的问题,我用的tmux
乱码的原因可能是:编译覆盖了正在运行的程序
另chuncked size: try { _sz = std::stoi(_sz_str, 0, 16); }catch(...){ throw Exception ("Unrecognized chunked size"); }
gzip chunked模式偶尔也会乱码。但是稳定性要强很多,能够从错误流中恢复
//解析错误在这里会被捕获,通过重连来解决
fv::Response _r;
try{
if (!session.IsConnect()) {
session = co_await fv::Session::FromUrl(host, "");
}
_r = co_await session.Get (host+ uri);
} catch (std::exception& e) {
std::cout<<"error:"<<e.what()<<"\n";
session.Conn->Reconnect();
}
乱码可能是不可避免的,这么解决可以接受
最好换一些稳定的后台url试试,确认是否就是这个网站服务器的Content-Length问题
"tickSz":"0.0001","uly":"ZRX-USDT"}],"msg":""}HTTP/1.1 200 Date: Thu, 19 May 2022 16:00:13 GMT Content-Type: application/json Content-Length: 77679 Connection: keep-alive Vary: Accept-Encoding Set-Cookie: locale=en-US; Max-Age=604800; Expires=Thu, 26-May-2022 16:00:13 GMT; Path=/ Set-Cookie: locale=en-US; Max-Age=604800; Expires=Thu, 26-May-2022 16:00:13 GMT; Path=/ X-BrokerID: 0 Strict-Transport-Security: max-age=63072000; includeSubdomains; preload
{"code":"0","data":[{"alias":"","baseCcy":"","category":"1","ctMult":"1","ctType":"inverse"