请问STM32+LAN+LWIP如何实现向HTTP接口发送大数据包?
这应该是个纯软件问题。我有个应用是通过STM32的虚拟U盘将电脑中的文件拷贝到STM32的EMMC中(单个文件从数MB到上GB),然后再通过STM32的以太网口上传到WEB后台。
(请别问为什么不通过电脑直接传而这么多此一举,问就是因为国情)
目前u盘的写入性能、fatfs的读取性能、tcp传输性能做单元测试都能满足性能要求了。
所问问题点在stm32向后台传输的性能问题。stm32无操作系统,直接用HAL框架。
我们开发人员不懂如何在单个http请求中发送超过tcp单帧数据包大小的请求体(也就是单请求只能发送一两k字节),目前的做法是发送一个大文件就需要拆成几千、几万甚至更多个http请求来发送。
这显然有明显的性能瓶颈,不是一种合理的方案。我知道http作为tcp的上层协议,它的单次请求额外开销是很大的,除了每次请求都要经过和服务器建立tcp连接三次握手,还要有http请求头和响应头的开销,以及http keep alive的处理。
我的嵌入式编程能力也是很弱的,所以想请教一下在stm32中如何实现像一般的HTTP请求中那样发送大量数据?
我纸上谈兵的想想,觉得要点在于实现emmc和eth两个外设的dma,以及如何和lwip的回调函数结合,实现一个尽量不间断的发送流水线,但还是觉得无从下手。{:dizzy:} 一帧最大1500个字节,数据量大,必须分包,这和stm32无关,也说不上纸上谈兵,基本逻辑就有问题 分块传输(Chunked Transfer Encoding):
在HTTP头中添加 Transfer-Encoding: chunked 字段。
将文件分成小块,并分别发送每个小块。
尝试过么😘
本帖最后由 honami520 于 2024-2-4 14:06 编辑
http是处于tcp上层的内容,至于那个一帧1500字节,是物理层的内容。
你做软件,按照http去发就行了,分包发送,一包1KB,然后一直发完你想发的不就好了。
好比你用lwip,你直接按照发送内容,底层的事情交给底层去做就完了。
我用lwip几秒钟发送几百KB的内容,运行很正常,一天多少GB web文件数据传输应该用FTP比较好把,FTP支持断点续传,可靠性强等优点;网上也有stm32移植FTP的例子,也比较好移植把;
http协议需要自己写文件的分包协议把,http是无状态协议,多个http请求到达服务器的顺序不一定是有序的;如果某一包后到服务器或者先到服务器就有问题,除非一包一包的发数据吗?
lb0857 发表于 2024-2-4 13:51
分块传输(Chunked Transfer Encoding):
在HTTP头中添加 Transfer-Encoding: chunked 字段。
将文件分 ...
(引用自3楼)
这个机制不是用来处理我所说的问题的。 honami520 发表于 2024-2-4 14:03
http是处于tcp上层的内容,至于那个一帧1500字节,是物理层的内容。
你做软件,按照http去发就行了,分包发 ...
(引用自4楼)
不知道你说的分包发送,是指一个http请求分成多个tcp包发送,还是直接分包成多个http请求?
lwip有高层的http接口吗?现在负责开发的人是自己用tcp封装了一个http请求出来,但是解决不了分成多个一个http分成多个tcp包发送的难题。
因为要传输的文件很大,分包是必须分包的,但是我不想分包到1536byte这么小的包。
比如一个HTTP POST请求体大致如下:
POST /server-url HTTP/1.0
HOST: www.example.com
Cookie: ....
Content-Length: 12345678
Content-Type: multipart/form-data
DATADATADATADATA...[省略10MB]
包越小,HTTP请求头和其他协议开销占比越大,效率越低。
另,上面的请求是自己构造出来的,比如请求头和请求体的结构是根据规范拼接出来的,但是请求体中的文件数据是从EMMC读出来的。
难点是:
1. 因为内存一共就几十k很有限,所以需要边拼装边传输。
2. 为了提高传输效率,充分利用stm32非常有限的外设连接速度,那么就最好能同时读emmc和传tcp,那我能想到的就是用dma了。如果读一下emmc再传一下eth吗,那等于打对折的效率。
3. 我不知道lwip有现成可用的满足上面要求的http客户端高级接口,我觉得只能自己封装,那么就需要上述2点和lwip回调函数相配合,在回调时,能给lwip的发送缓冲区中及时填装数据。
在java中,这种一般通过stream接口来实现,但是在stm32中如何搞就没头绪了。
可能我的思路本身就和嵌入式不兼容吧。 26消费者 发表于 2024-2-4 14:20
web文件数据传输应该用FTP比较好把,FTP支持断点续传,可靠性强等优点;网上也有stm32移植FTP的例子,也比 ...
(引用自5楼)
我们现在就是分成1k多的小包的,服务器收到多个小包后再拼起来。顺序错乱可以通过自己传输一个包顺序来解决的。
所以你说的问题可以解决。
至于FTP,它在很多场合下是不方便的,因为大型机构的防火墙一般是不会开放ftp端口的,但是开放80端口就很正常。
况且ftp还存在主动模式(20/21端口)和被动模式(21+动态端口),对防火墙配置来说非常不友好。 akey3000 发表于 2024-2-4 13:31
一帧最大1500个字节,数据量大,必须分包,这和stm32无关,也说不上纸上谈兵,基本逻辑就有问题 ...
(引用自2楼)
没有逻辑问题,只是我提的问题比较绕,我在7楼又补充描述了。😁 TCP最大不是1500字节一包,还有没做那么多缓存。我司发送升级包是把升级包按配置payload大小分(256,512Byte),每包有序号和校验,整个升级包也有校验码,支持断点续传。不过就是传几百KB东西。 Rabbitoose 发表于 2024-2-4 14:47
不知道你说的分包发送,是指一个http请求分成多个tcp包发送,还是直接分包成多个http请求?
lwip有高层 ...
(引用自7楼)
分块,把Content-Length: 12345678删除,加上Transfer-encoding: chunked,后面每一块是 块长度<CR><LF>数据<CR><LF>,最后一块长度是0<CR><LF>,对方就知道发完了,可以分块准备数据。 本帖最后由 honami520 于 2024-2-4 17:07 编辑
Rabbitoose 发表于 2024-2-4 14:51
我们现在就是分成1k多的小包的,服务器收到多个小包后再拼起来。顺序错乱可以通过自己传输一个包顺序来解 ...
(引用自8楼)
lwip里面有专门的http的例子,不过那个我当初用的时候,在发送完成,等应答的时候,偶尔会出现30秒超时。
后来我就直接用tcp,然后也是自己封包成http去发送、解析了。
整个通信过程就是用lwip里面的socket来实现的,具体的流程是:
1、首先把发送的数据,按照http要求来重新封包(其实就是增加一些头信息)
2、创建一个socket,然后去连接服务器
3、连接成功后,就按照1KB来不断的write(lwip里面的函数),直到write完成
4、发送完成后,就不断read,直到读取到内容,或者超时退出
LWIP里面也有个缓存的,并不是我每次write 1KB进去,它就会马上发送出去。它也会攒一些数据,然后才真正去执行底层发送。
我一次write 10-20KB,对我来说效果也都是差不多的。因为跑lwip的时候肯定是用RTOS了。
那个1500字节,你不用特别在意,人家都给你想好了的
而且tcp通信,根本不存在你说的多个小包拼起来,它是连续的。不过网络不好的时候也许会出现一些特殊情况,丢数据也是有可能。
但是网络正常的时候,根本不存在顺序错乱 Rabbitoose 发表于 2024-2-4 14:51
我们现在就是分成1k多的小包的,服务器收到多个小包后再拼起来。顺序错乱可以通过自己传输一个包顺序来解 ...
(引用自8楼)
不懂为何包要分这么小,tcp本来就是流,你发了http头后后面就是emmc到tcp流的数据拷贝传输,没有说一定要在一个ip帧里面 honami520 发表于 2024-2-4 17:00
lwip里面有专门的http的例子,不过那个我当初用的时候,在发送完成,等应答的时候,偶尔会出现30秒超时。 ...
(引用自12楼)
那你一般能达到多少传输速度呢?我现在大约有3MB的样子,我主要的目的是提高速度。 honami520 发表于 2024-2-4 14:03
http是处于tcp上层的内容,至于那个一帧1500字节,是物理层的内容。
你做软件,按照http去发就行了,分包发 ...
(引用自4楼)
对。
网卡一包1.5K和http一个请求能装多少,根本就没有一点关系。
http只能看到tcp的数据流,
tcp才能看到下面一层是网卡的数据帧。
http发请求只是调用tcp层,传递一个数据流,长度自己决定。你可以一边生成数据,一边往下写,跟你内存大小都没关系。你可以一下子生成差不多快装满内存的数据,然后发完,继续再生成就是。
如果预先不知道数据长度,有两招,一个是上面说的chunked,还有另一招是改成http1.0,不带content-length,而是发完数据了就关闭连接。这样更简单。 本帖最后由 albert_w 于 2024-2-5 01:00 编辑
http上传,做好头部和尾部中间文件流往上传就可以了,中间就纯tcp包。头部有分隔符来识别http结束的
问题是如果文件太大网络不好,还是要对http分包,把文件割成多块上传。失败哪块传哪块。至于块多大看你文件和网络了。1xxx肯定不合适,太碎了,比如128k甚至几M
页:
[1]