sprinfall / webcc

Lightweight C++ HTTP client and server library based on Asio for embedding purpose.
GNU Lesser General Public License v3.0
270 stars 61 forks source link

如何修改每次只读取1024字节 #19

Closed Thewolfinsociety closed 3 years ago

Thewolfinsociety commented 3 years ago

2020-12-14 12:11:43.173, VERB, main, client.cc, 247, Timer canceled. 2020-12-14 12:11:43.182, INFO, main, client.cc, 208, Read data, length: 1024. 2020-12-14 12:11:43.194, VERB, main, client.cc, 237, Wait timer asynchronously.

Thewolfinsociety commented 3 years ago

您好,我接收一个请求响应1M数据的字符串,每次只读取1024字节数据,所以获取所有数据就非常慢,如何优化呢。

Thewolfinsociety commented 3 years ago

您好,我通过读取源码,明白了由于缓存区默认1024字节,所以速度慢。我通过set_buffer_size调整了这个数据就便快多了。但是我设置多大合适呢?

sprinfall commented 3 years ago

您好,我通过读取源码,明白了由于缓存区默认1024字节,所以速度慢。我通过set_buffer_size调整了这个数据就便快多了。但是我设置多大合适呢?

设置为 1024 * 10 应该就差不多了,但这个也取决于您的 server 每次 write 时写多少。 但我本人目前对 socket 读写的理解还比较浅显,所以您不妨递增地调整这个值,直到响应时间没有明显改进为止,然后设置这个值就可以了。 如果某个特定的接口,响应数据特别小或特别多,也可以分别对这个值进行设置(如果没有使用 Keep-Alive 的话,如果使用了 Keep-Alive,多次调用用的都是同一个 Client 对象,动态调整 buffer 缓冲的意义不大吧)。

Thewolfinsociety commented 3 years ago

谢谢您的回复

Thewolfinsociety commented 3 years ago

您好,我还想请教下,auto r = session.Send(webcc::RequestBuilder{}. Post(url). Query()()); Query 能否和body接收参数一样呢,接收json字符串;很多参数,只使用一个Query就行我觉得这样用起来较为方便。如果用body,普通方式不能获取到参数,而需要server解析请求body,较为麻烦不常用。

sprinfall commented 3 years ago

您好,我还想请教下,auto r = session.Send(webcc::RequestBuilder{}. Post(url). Query()()); Query 能否和body接收参数一样呢,接收json字符串;很多参数,只使用一个Query就行我觉得这样用起来较为方便。如果用body,普通方式不能获取到参数,而需要server解析请求body,较为麻烦不常用。

传 JSON 字符串给 Query(),需要你自己先生成 JSON 字符串,然后指定参数 encode = true,这样应该可以吧。

Thewolfinsociety commented 3 years ago

这样是可以请求的;我想问下您为什么我设置session.SetContentType("application/x-www-form-urlencoded","utf-8"); 不成功,后台一直显示Content-Type: application/json; charset=utf-8 ,这是为什么呢

Thewolfinsociety commented 3 years ago

请问您,当响应内容Content-Encoding = gzip, 直接r->data() 会报错;2020-12-16 16:23:37.224, ERRO, main, response_parser.cc, 52, Invalid HTTP response status line: HTTP/1.1 200 ; 看您给的readme例子没有相关设置,请问如何设置呢

sprinfall commented 3 years ago

请问您,当响应内容Content-Encoding = gzip, 直接r->data() 会报错;2020-12-16 16:23:37.224, ERRO, main, response_parser.cc, 52, Invalid HTTP response status line: HTTP/1.1 200 ; 看您给的readme例子没有相关设置,请问如何设置呢

这是一个问题,应答的 status line 缺少 reason 字段(在 200 后面为空格),这是 webcc 兼容性的问题,我待会改一下。

sprinfall commented 3 years ago

请问您,当响应内容Content-Encoding = gzip, 直接r->data() 会报错;2020-12-16 16:23:37.224, ERRO, main, response_parser.cc, 52, Invalid HTTP response status line: HTTP/1.1 200 ; 看您给的readme例子没有相关设置,请问如何设置呢

这是一个问题,应答的 status line 缺少 reason 字段(在 200 后面为空格),这是 webcc 兼容性的问题,我待会改一下。

改好了,你试一下新代码。

Thewolfinsociety commented 3 years ago

好谢谢你,我刚分析源码发现了

sprinfall commented 3 years ago

您好,我还想请教下,auto r = session.Send(webcc::RequestBuilder{}. Post(url). Query()()); Query 能否和body接收参数一样呢,接收json字符串;很多参数,只使用一个Query就行我觉得这样用起来较为方便。如果用body,普通方式不能获取到参数,而需要server解析请求body,较为麻烦不常用。

传 JSON 字符串给 Query(),需要你自己先生成 JSON 字符串,然后指定参数 encode = true,这样应该可以吧。

我看了一下这篇讨论: https://stackoverflow.com/questions/4007969/application-x-www-form-urlencoded-or-multipart-form-data

觉得你这样用是不对的,RequestBuilder 的 Query() 只是给 GET 方法用的,它会把参数编码后跟在 URL 后面。

针对你的情形,试试先通过 UrlQuery 类(见 url.h)自己组装一个 query 对象,然后调用 UrlQuery::ToString() 生成一个最终的字符串,最后把这个字符串作为 body 设置给 Post 请求。此外,有了 body,session.SetContentType 就能生效了。

Thewolfinsociety commented 3 years ago

我最开始也是觉得body 够用了,但是我发现session.SetContentType 一直不成功,Python构造的服务端一直显示Content-Type: application/json; charset=utf-8

Thewolfinsociety commented 3 years ago

session.SetContentType("application/x-www-form-urlencoded","utf-8"); 这样设置的

Thewolfinsociety commented 3 years ago

测试发现,1.有body,request无header设置SetContentType 设置不成功,2.没有body 用Query + webcc::RequestBuilder{}.Header()设置成功;3.没有body 用Query +session.SetContentType 设置不成功。

sprinfall commented 3 years ago

我给你加了个例子,见:examples/form_urlencoded_client.cc 希望能帮到你。

sprinfall commented 3 years ago

session.SetContentType() 的作用是为一个 session 里发起的所有请求提供“缺省”的 ContentType,只有当一个请求有 Body 并且它自己没设置 Content-Type 头时才会应用。

Thewolfinsociety commented 3 years ago

谢谢您耐心的不吝赐教,我按照您给的例子成功跑通了。十分感谢

sprinfall commented 3 years ago

谢谢您耐心的不吝赐教,我按照您给的例子成功跑通了。十分感谢

不用谢,我也学到了很多。我对 HTTP 协议的理解还有很多不足,后面如果接口有对 urlencoded form 做优化的话,再通知你。