本帖最后由 mii 于 2017-8-31 20:12 编辑
使用开发板平台是
STM32F429 + LAN8720a,LWIP版本是1.4.1.
测试例程开发板自己带例程,主要移植了ST的ETH库。测试例程实现在裸跑情况下开发板建立一个服务端,使用TCP调试助手连接,发送、接收同样数据的回环测试。
下面是接收回调函数,开发板例程原程序,中文注释为返回接收到数据。
- static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
- {
- #ifdef SERIAL_DEBUG
- char *recdata=0;
- #endif
-
- struct tcp_echoserver_struct *es;
- err_t ret_err;
- LWIP_ASSERT("arg != NULL",arg != NULL);
-
- es = (struct tcp_echoserver_struct *)arg;
-
- /* if we receive an empty tcp frame from client => close connection */
- if (p == NULL)
- {
- /* remote host closed connection */
- es->state = ES_CLOSING;
- if(es->p == NULL)
- {
- /* we're done sending, close connection */
- tcp_echoserver_connection_close(tpcb, es);
- }
- else
- {
- /* we're not done yet */
- /* acknowledge received packet */
- tcp_sent(tpcb, tcp_echoserver_sent);
-
- /* send remaining data*/
- tcp_echoserver_send(tpcb, es);
- }
- ret_err = ERR_OK;
- }
- /* else : a non empty frame was received from client but for some reason err != ERR_OK */
- else if(err != ERR_OK)
- {
- /* free received pbuf*/
- es->p = NULL;
- pbuf_free(p);
- ret_err = err;
- }
- else if(es->state == ES_ACCEPTED)
- {
- /* first data chunk in p->payload */
- es->state = ES_RECEIVED;
-
- /* store reference to incoming pbuf (chain) */
- es->p = p;
-
- /* initialize LwIP tcp_sent callback function */
- tcp_sent(tpcb, tcp_echoserver_sent);
-
- #ifdef SERIAL_DEBUG
- recdata=(char *)malloc(p->len*sizeof(char));
- if(recdata!=NULL)
- {
- memcpy(recdata,p->payload,p->len);
- printf("upd_rec:%s",recdata);
- }
- free(recdata);
- #endif
-
- /* send back the received data (echo) */
- tcp_echoserver_send(tpcb, es);
-
- ret_err = ERR_OK;
- }
- else if (es->state == ES_RECEIVED)
- {
- /* more data received from client and previous data has been already sent*/
- if(es->p == NULL)
- {
- es->p = p;
-
- #ifdef SERIAL_DEBUG
- recdata=(char *)malloc(p->len*sizeof(char));
- if(recdata!=NULL)
- {
- memcpy(recdata,p->payload,p->len);
- printf("upd_rec:%s",recdata);
- }
- free(recdata);
- #endif
-
- /* send back received data */
- tcp_echoserver_send(tpcb, es);//返回接收到数据
- }
- else
- {
- struct pbuf *ptr;
- /* chain pbufs to the end of what we recv'ed previously */
- ptr = es->p;
- pbuf_chain(ptr,p);
- }
- 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 */
- es->p = NULL;
- pbuf_free(p);
- ret_err = ERR_OK;
- }
- return ret_err;
- }
复制代码
以上回环测试中,随便发送一个字符串,1ms发送接收都不会卡死。
然而修改后,注意中文注释。只想实现只要接收数据就发送一个数组数据。下面是修改后程序
- static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
- {
- char HeartDatSend[5] = {0x01,0x02,0x03,0x04,0x05};
- #ifdef SERIAL_DEBUG
- char *recdata=0;
- #endif
-
- struct pbuf *spbuf;
-
- struct tcp_echoserver_struct *es;
- err_t ret_err;
- LWIP_ASSERT("arg != NULL",arg != NULL);
-
- es = (struct tcp_echoserver_struct *)arg;
-
- /* if we receive an empty tcp frame from client => close connection */
- if (p == NULL)
- {
- /* remote host closed connection */
- es->state = ES_CLOSING;
- if(es->p == NULL)
- {
- /* we're done sending, close connection */
- tcp_echoserver_connection_close(tpcb, es);
- }
- else
- {
- /* we're not done yet */
- /* acknowledge received packet */
- tcp_sent(tpcb, tcp_echoserver_sent);
-
- /* send remaining data*/
- tcp_echoserver_send(tpcb, es);
- }
- ret_err = ERR_OK;
- }
- /* else : a non empty frame was received from client but for some reason err != ERR_OK */
- else if(err != ERR_OK)
- {
- /* free received pbuf*/
- es->p = NULL;
- pbuf_free(p);
- ret_err = err;
- }
- else if(es->state == ES_ACCEPTED)
- {
- /* first data chunk in p->payload */
- es->state = ES_RECEIVED;
-
- /* store reference to incoming pbuf (chain) */
- es->p = p;
-
- /* initialize LwIP tcp_sent callback function */
- tcp_sent(tpcb, tcp_echoserver_sent);
-
- #ifdef SERIAL_DEBUG
- recdata=(char *)malloc(p->len*sizeof(char));
- if(recdata!=NULL)
- {
- memcpy(recdata,p->payload,p->len);
- printf("upd_rec:%s",recdata);
- }
- free(recdata);
- #endif
-
- /* send back the received data (echo) */
- tcp_echoserver_send(tpcb, es);
-
- ret_err = ERR_OK;
- }
- else if (es->state == ES_RECEIVED)
- {
- /* more data received from client and previous data has been already sent*/
- if(es->p == NULL)
- {
- es->p = p;
-
- #ifdef SERIAL_DEBUG
- recdata=(char *)malloc(p->len*sizeof(char));
- if(recdata!=NULL)
- {
- memcpy(recdata,p->payload,p->len);
- printf("upd_rec:%s",recdata);
- }
- free(recdata);
- #endif
-
- spbuf = pbuf_alloc(PBUF_TRANSPORT,256,PBUF_RAM);//开一个新缓冲
- spbuf->payload = HeartDatSend;//装载数据
- spbuf->len = sizeof(HeartDatSend)/sizeof(HeartDatSend[0]);//设置发送长度
- spbuf->tot_len = sizeof(HeartDatSend)/sizeof(HeartDatSend[0]);//设备总长度
- es->p = spbuf;//将缓冲更新到要发送PCB中
-
- /* send back received data */
- tcp_echoserver_send(tpcb, es);//发送
- // tcp_echoserver_send(es->pcb, es);
- pbuf_free(spbuf);//释放缓冲区
- }
- else
- {
- struct pbuf *ptr;
- /* chain pbufs to the end of what we recv'ed previously */
- ptr = es->p;
- pbuf_chain(ptr,p);
- }
- 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 */
- es->p = NULL;
- pbuf_free(p);
- ret_err = ERR_OK;
- }
- return ret_err;
- }
复制代码
然而上面测试中,可能有十次回环左右是成功的,然后就会卡死了协议栈。用WireSark捕捉出来的数据是发生多次重连,下面是截图
微信截图_20170831200527.png (61.32 KB, 下载次数: 0)
下载附件
2017-8-31 20:07 上传
就以上情况,摸索了好几天都没想明白,请教一下怎么解决这种情况?
明白,我试试
感谢大神指点,确实要用PBUF的专用函数就不会出现问题。感谢,发送部分修改如下,
- spbuf = pbuf_alloc(PBUF_TRANSPORT,strlen((char*)HeartDatSend),PBUF_RAM);
- pbuf_take(es->p, (char*)HeartDatSend, strlen((char*)HeartDatSend));
-
-
- /* send back received data */
- tcp_echoserver_send(tpcb, es);
- pbuf_free(spbuf);
复制代码大神,上次使用PBUF_take这个函数装载是没有问题,但发送数据长度不对。就是我只复制了5个字节,但会发出11个字节数据。
单步调试发现这个函数只会简单对初始的缓冲区域进行覆盖,不会调整发送长度 。
我自己去手动调整发送长度的话,发送一会,接收窗口就变成0了。
这个应该怎么解决
一周热门 更多>