LwIP TCP Client 解决长数据发送的困扰
问题描述
LWIP 的 TCP Client 发送数据可以调用 tcp_write() 函数,将数据储存在缓冲区里面,然后等待超时自动发送或者调用tcp_output()函数进行发送。
然而 tcp_write() 函数 需要发送的数据过长时,将无法发送,并返回 ERR_MEM。
tcp_write()函数解析
tcp_write()的函数代码很多,就不细看代码了,
先看tcp_write()的完整函数:
err_t tcp_write(struct tcp_pcb *pcb, const void *arg, u16_t len, u8_t apiflags)
其中 pcb 是TCP协议块
arg 是待发送数据指针
len 是待发送数据长度
apiflags 是发送的方式,如果是1,则发送的时候,会复制数据到缓存进行发送,如果是2,则发送过程中arg的数据不能变化
如何解决发送长度的问题
看官方注释:
* The proper way to use this function is to call the function with at* most tcp_sndbuf() bytes of data. If the function returns ERR_MEM,* the application should wait until some of the currently enqueued* data has been successfully received by the other host and try again.
翻译过来的意思就是:
使用此函数的正确方法是使用最多tcp_sndbuf()字节的数据调用该函数。如果函数返回ERR_MEM,应用程序应该等待,直到当前排队的数据被其他主机成功接收,然后再试一次。
其中tcp_sndbuf() 是一个宏定义, 最终是指pcb结构体里的 tcpwnd_size_t snd_buf;
/* Available buffer space for sending (in bytes). */
也就是一次发送的最大字节数。
由此可知,我们发送长数据的时候,只需要连续分包发送,且每次发送小于tcp_sndbuf()字节,就可以实现长数据发送了
最终实现长数据发送函数
最后附上已实现的函数,配合FREERTOS,就可以发送长数据了,实测稳定可用。
int my_tcp_write_eth(uint8_t * Buf,int Size)
{int try_time = 0;int send_pack_index = 0;if(Size == 0)return 0;err_t err_status;int sizemax = 500;//tcp_sndbuf(client_pcb);send_pack:if(try_time >= 150){printf("TCP发送失败! ERR_MEM \n");return -1;}if(Size == 0)return 1;if(Size <= sizemax){err_status = tcp_write(client_pcb, &Buf[send_pack_index * sizemax], Size , 1);if(err_status != ERR_OK){if(err_status == ERR_MEM){// printf("TCP发送失败!数据太长%u\n",Size); osDelay(5);try_time ++;goto send_pack;}elseprintf("TCP发送失败!\n");//tcp_err(client_pcb, client_err); return -1;}//立刻发送if(tcp_output(client_pcb) != ERR_OK){printf("TCP发送失败!\n");return -1; }return 1;}else{//printf("数据大于sizemax,分包发送! %u\n",send_pack_index);err_status = tcp_write(client_pcb, &Buf[send_pack_index * 500], 500, 1);if(err_status != ERR_OK){if(err_status == ERR_MEM){// printf("TCP发送失败!数据太长%u\n",Size);osDelay(5);try_time ++;goto send_pack;}elseprintf("TCP发送失败!\n");//tcp_err(client_pcb, client_err); return -1;}//立刻发送if(tcp_output(client_pcb) != ERR_OK){printf("TCP发送失败!\n");return -1; }try_time = 0;Size -= sizemax;// printf("发送完成! 剩余 %u 字节需要发送\n",Size);send_pack_index ++;goto send_pack;}}
LwIP TCP Client 解决长数据发送的困扰相关推荐
- nodejs TCP server和TCP client如何进行数据交互
使用Jerry之前的文件成功建立服务器端和客户端的TCP连接后,客户端得到一个client实例: async function startClient(ip = configJson.TCP.clie ...
- Java实现crc16校验 附上校验工具对照。解决长数据校验不正确的问题
Android与底层硬件通信,进行CRC16校验时,要考虑到无符号整形的原因,java会将超过的值变成负数 C算法: Uint16 crc16 = 0; Uint8 i = 0; Uint16 Cr ...
- TCP窗口调整与数据流控制以及病态窗口症状
TCP协议主要依赖不断调整窗口大小来保证数据收发吞吐率.在三次握手时,客户端会告诉服务器自己一次能接收数据量的大小,这就对应客户端的接收窗口以及服务器的发送端口.同理服务器也会告知客户端它一次能接收的 ...
- 串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx
引言:对于串口接收一些不定长的数据,必须面对一个问题:怎么判断一帧数据接收是否完成?通常使用RXNE非空中断配合简单的数据协议,在数据中加入帧头.帧尾,在程序中判断是否接收到帧尾来确定数据接收完毕,因 ...
- LwIP C TCP/IP Stack 正确的TCP连接数据发送姿态
注意,本文提供的代码来自本人搞起耍的 netstack,有一些类似 tun2socks LwIP 实现,目前不会考虑集成到产品上面作为可选 TCP/IP 网络栈,当然不会是基于 go-gvisor.g ...
- moxa Nport配置tcp/udp实现数据发送和回传(补充数据接收错乱处理方法)
moxa Nport配置tcp/udp实现数据发送和回传–记一次吐血经历 目的 现有一内网环境需要连外网进行钉钉推送,开始使用串口连接实体电脑的方式实现,现需要撤除实体电脑,故选用串口服务器的方式实现 ...
- lwip连续发数据卡死_LwIP用TCP连接方式在数据量比较大协议栈卡死
这段时间用STM32移植LwIP做语音传输.但是遇到一个问题困扰许久,在使用TCP方式做一个client去连接server,由于数据量比较大经常在连接一个多小时候就出现断线而 也ping不通.接下来我 ...
- Android之间互相的录屏直播 --点对点传输(tcp长连接发送h264)(一)
前言 转载请注明出处 ,来自: 暂时两篇: (1) Android之间互相的录屏直播 –点对点传输(tcp长连接发送h264)(一) http://blog.csdn.net/baidu_335462 ...
- linux 内核 发送数据,linux 内核tcp数据发送的实现
在分析之前先来看下SO_RCVTIMEO和SO_SNDTIMEO套接口吧,前面分析代码时没太注意这两个.这里算是个补充. SO_RCVTIMEO和SO_SNDTIMEO套接口选项可以给套接口的读和写, ...
最新文章
- python中删除列表中的空元素以及如何读取excel中的数据
- centos 6推荐使用epel源
- 设计模式:单例模式之双重检查
- boost::hana模块在无限可迭代对象上测试 hana::index_if
- 安装OpenLDAP
- Ubuntu首次登入与在线求助man page总结
- Spartacus image alt属性的绑定实现
- win7系统怎么更改语言及字体
- 复杂链表的复制(C++解法)
- 【渝粤教育】国家开放大学2018年春季 8647-21T工程经济与管理 参考试题
- MaxCompute/DataWorks权限问题排查建议
- 基于AT89C51单片机的超声波传感器测距【程序详细代码及注释】
- 计算机专业英文授课,计算机专业全英文授课分析
- 项目管理的七个工作法则
- 统计字符个数怎么用c语言写,请问这个用c怎么做:输入一串字符,分别统计其中数字和字母的个数...
- WORD/WPS打印目录或输出输出PDF时,目录显示“错误未定义标签”,且无法正常跳转的解决方法
- echo相关参数 -e -n
- 一卡通变“一脸通”,人脸识别让校园更安全
- springboot整合redis、mybatis、@EnableScheduling定时任务,实现日访问量与日活量的统计与记录
- Matlab画线性规划可行域