| 问题描述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;
	
	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)
			{
		
				osDelay(5);
				try_time ++;
				goto send_pack;
			}
			else
				printf("TCP发送失败!\n");
				
			return -1;
		}
		
			
			if(tcp_output(client_pcb) != ERR_OK)
			{
				printf("TCP发送失败!\n");
				return -1;	
			}
		
		return 1;
	}
	else
	{
		  
		
			err_status = tcp_write(client_pcb, &Buf[send_pack_index * 500], 500, 1);
			
			if(err_status != ERR_OK)
			{
				if(err_status == ERR_MEM)
				{
				
					osDelay(5);
					try_time ++;
					goto send_pack;
				}
				else
					printf("TCP发送失败!\n");
					
				return -1;
			}
			
			
			if(tcp_output(client_pcb) != ERR_OK)
			{
				printf("TCP发送失败!\n");
				return -1;	
			}
			
			
			try_time = 0;
			
			
			Size -= sizemax;
			
		
			
			send_pack_index ++;
			
			goto send_pack;
	}
	
}
 |