开发板为STM32F429+LWIP,作为TCP\IP客户端;
电脑作为服务端进行测试;
问题1、LWIP怎么释放发送数据的缓存
LWIP TCP/IP客户端发送数据后,服务端会发送一个ACk确认包;
客户端收到ACK包后,会进入 ETH_IRQHandler中断函数中,对已发送数据包占用的缓存进行清空操作;
如果程序中没有配置 ETH_IRQHandler中断函数,则每发送一个数据包后,再tcp_write()、tcp_out()后面调用
while( ETH_CheckFrameReceived() ) { LwIP_Pkt_Handle(); } 进行缓存区的清空;
///
void ETH_IRQHandler(void)
{
/* Handles all the received frames */
/* check if any packet received */
while(ETH_CheckFrameReceived())
{
/* process received ethernet packet */
LwIP_Pkt_Handle();
}
/* Clear the Eth DMA Rx IT pending bits */
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
}
问题2、怎么检测到LWIP网络断开
服务端断开连接后,会给客户端发送FIN包,LWIP会进入接收回调函数中tcp_client_recv();
在接收回调函数中,判断为空的数据包,则为服务端断开连接了;调用tcp_echoclient_connection_close(tpcb, es);进行关断。
static err_t tcp_echoclient_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
char *recdata=0;
struct echoclient *es;
err_t ret_err;
LWIP_ASSERT("arg != NULL",arg != NULL);
es = (struct echoclient *)arg;
/* if we receive an empty tcp frame from server => close connection */
if (p == NULL)
{
/* remote host closed connection */
es->state = ES_CLOSING;
tcp_echoclient_connection_close(tpcb, es);
ret_err = ERR_OK;
}
/* else : a non empty frame was received from echo server but for some reason err != ERR_OK */
else if(err != ERR_OK)
{
/* free received pbuf*/
pbuf_free(p);
ret_err = err;
}
else if(es->state == ES_CONNECTED)
{
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
//add by cjh 2017-12-26
tcp_echoclient_cmd_handle( p->payload , p->len );
ret_err = ERR_OK;
}
/* data received when connection already closed */
else
{
/* Acknowledge data reception */
tcp_recved(tpcb, p->tot_len);
/* free pbuf and do nothing */
pbuf_free(p);
ret_err = ERR_OK;
}
return ret_err;
}
注意:tcp_echoclient_connection_close(tpcb, es);中的处理要注意的地方;记得调用tcp_abort()函数,才能把建立的tcp链表缓存给释放掉。
//关闭与服务器的连接
void tcp_echoclient_connection_close(struct tcp_pcb *tpcb, struct tcp_client_struct * es)
{
//移除回调
if(tpcb)
{
tcp_abort(tpcb);//终止连接,删除pcb控制块
tcp_arg(tpcb,NULL);
tcp_recv(tpcb,NULL);
tcp_sent(tpcb,NULL);
tcp_err(tpcb,NULL);
tcp_poll(tpcb,NULL,0);
}
if(es)mem_free(es);
tcp_client_flag&=~(1<<5);//标记连接断开了
}