问题描述

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 解决长数据发送的困扰相关推荐

  1. nodejs TCP server和TCP client如何进行数据交互

    使用Jerry之前的文件成功建立服务器端和客户端的TCP连接后,客户端得到一个client实例: async function startClient(ip = configJson.TCP.clie ...

  2. Java实现crc16校验 附上校验工具对照。解决长数据校验不正确的问题

    Android与底层硬件通信,进行CRC16校验时,要考虑到无符号整形的原因,java会将超过的值变成负数 C算法: Uint16 crc16 = 0; Uint8  i = 0; Uint16 Cr ...

  3. TCP窗口调整与数据流控制以及病态窗口症状

    TCP协议主要依赖不断调整窗口大小来保证数据收发吞吐率.在三次握手时,客户端会告诉服务器自己一次能接收数据量的大小,这就对应客户端的接收窗口以及服务器的发送端口.同理服务器也会告知客户端它一次能接收的 ...

  4. 串口IDLE空闲中断+DMA实现接收不定长数据基于stm32cubemx

    引言:对于串口接收一些不定长的数据,必须面对一个问题:怎么判断一帧数据接收是否完成?通常使用RXNE非空中断配合简单的数据协议,在数据中加入帧头.帧尾,在程序中判断是否接收到帧尾来确定数据接收完毕,因 ...

  5. LwIP C TCP/IP Stack 正确的TCP连接数据发送姿态

    注意,本文提供的代码来自本人搞起耍的 netstack,有一些类似 tun2socks LwIP 实现,目前不会考虑集成到产品上面作为可选 TCP/IP 网络栈,当然不会是基于 go-gvisor.g ...

  6. moxa Nport配置tcp/udp实现数据发送和回传(补充数据接收错乱处理方法)

    moxa Nport配置tcp/udp实现数据发送和回传–记一次吐血经历 目的 现有一内网环境需要连外网进行钉钉推送,开始使用串口连接实体电脑的方式实现,现需要撤除实体电脑,故选用串口服务器的方式实现 ...

  7. lwip连续发数据卡死_LwIP用TCP连接方式在数据量比较大协议栈卡死

    这段时间用STM32移植LwIP做语音传输.但是遇到一个问题困扰许久,在使用TCP方式做一个client去连接server,由于数据量比较大经常在连接一个多小时候就出现断线而 也ping不通.接下来我 ...

  8. Android之间互相的录屏直播 --点对点传输(tcp长连接发送h264)(一)

    前言 转载请注明出处 ,来自: 暂时两篇: (1) Android之间互相的录屏直播 –点对点传输(tcp长连接发送h264)(一) http://blog.csdn.net/baidu_335462 ...

  9. linux 内核 发送数据,linux 内核tcp数据发送的实现

    在分析之前先来看下SO_RCVTIMEO和SO_SNDTIMEO套接口吧,前面分析代码时没太注意这两个.这里算是个补充. SO_RCVTIMEO和SO_SNDTIMEO套接口选项可以给套接口的读和写, ...

最新文章

  1. python中删除列表中的空元素以及如何读取excel中的数据
  2. centos 6推荐使用epel源
  3. 设计模式:单例模式之双重检查
  4. boost::hana模块在无限可迭代对象上测试 hana::index_if
  5. 安装OpenLDAP
  6. Ubuntu首次登入与在线求助man page总结
  7. Spartacus image alt属性的绑定实现
  8. win7系统怎么更改语言及字体
  9. 复杂链表的复制(C++解法)
  10. 【渝粤教育】国家开放大学2018年春季 8647-21T工程经济与管理 参考试题
  11. MaxCompute/DataWorks权限问题排查建议
  12. 基于AT89C51单片机的超声波传感器测距【程序详细代码及注释】
  13. 计算机专业英文授课,计算机专业全英文授课分析
  14. 项目管理的七个工作法则
  15. 统计字符个数怎么用c语言写,请问这个用c怎么做:输入一串字符,分别统计其中数字和字母的个数...
  16. WORD/WPS打印目录或输出输出PDF时,目录显示“错误未定义标签”,且无法正常跳转的解决方法
  17. echo相关参数 -e -n
  18. 一卡通变“一脸通”,人脸识别让校园更安全
  19. springboot整合redis、mybatis、@EnableScheduling定时任务,实现日访问量与日活量的统计与记录
  20. Matlab画线性规划可行域

热门文章

  1. 等离子与液晶电视:谁是未来彩电主角?
  2. 1389. 玩诈欺的小杉【推荐】
  3. 关于DHCP、VLAN、混杂模式解惑
  4. python全栈讲解_Python全栈数据工程师养成攻略(视频讲解版)
  5. redis的三种集群模式原理
  6. Master PDF Editor(PDF编辑工具)v5.4.04中文免费版
  7. linux守护进程写法_Linux守护进程的深入理解
  8. 移动通信数字移动电话客户号码结构
  9. EM算法高斯混合模型原理详解及小例子
  10. 单片机c语言编程下载,单片机C语言编程.doc