tcp接收数据中途--断线,求大神支招。

2019-08-14 20:18发布

通过客户端(手机)控制设备(裸机,无系统),系统架构为手机发送给云服务器,服务器转发给mqtt代理,代理再发送给设备。每按一下按键发送同一条控制指令。在连续按键一段时间后出现tcp断开连接的现象。无论按动的频率多慢,1秒按一次也会掉线;出错时间也不定,有时按到第30多次掉线,有时按到10多次就掉线了。我在自己电脑上配置了一个mqtt客户端,订阅同一个主题,能正确收到每次按键的控制指令,个人认为客户端下发的指令至少顺利到达mqtt代理,并且mqtt代理也正常的将数据发送出去了,所以问题就只能出在我的设备上。最可能的,我想还应该是tcp初始化的问题。这种判断对吗?下面是TCP客户端初始化函数,使用的协议栈为lwip 1.4.1,程序都是参照网上的例程修修改改而来,新手接触lwip,让大家见笑了。出错的地方使用红 {MOD}字标出,有两个问题我一直不解:1、接收函数中在什么情况下回出现pbuf p == NULL?是接收到了类似ACK这种数据为空的数据包吗? 2、接收函数的返回值err_t err == ERR_OK是个什么概念?ERR_OK不是表示无错误(正常)么?为什么检测到出现这种状态时好像是在处理一个错误一样的将tcp关闭呢? 这个问题卡住我几天了。求大神支招。感激不尽。err_t tcp_Init(void){                 err_t err;         struct ip_addr serverIp;         IP4_ADDR( &serverIp,192.168.2.120);  /*设置服务器IP*/         iot_client_pcb = tcp_new();    err= tcp_connect(iot_client_pcb,&serverIp,MQTT_SERVER_PORT,iot_tcp_accept);         return err;}err_tiot_tcp_accept(void *arg, struct tcp_pcb *newpcb, err_t err){  //监听到新的客户端连接请求   err_t ret_err;  UdpStdioPrintf("iot_tcp_accept!");  tcp_recv(newpcb,iot_tcp_recv); //指定回调函数  tcp_err(newpcb,iot_tcp_error); //指定错误函数  tcp_poll(newpcb,iot_tcp_poll,1);                  //指定轮询函数  mqttConnect();       /*连接MQTT服务器*/           return ret_err;  } err_tiot_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err){  char *buf;  uchar mqttCmd;  err_t ret_err = ERR_OK;    struct name *name = (struct name *)arg;  UdpStdioPrintf("iot_client_recv");  if (p != NULL)   {                UdpStdioPrintf("------------------------1!");         tcp_recved(tpcb, p->tot_len);    buf = p->payload;         mqttCmd = (*buf & 0xf0) >> 4;         switch(mqttCmd) {          case PUBLISH:                   {                       UdpStdioPrintf("Publish In!");                   } break;          case CONNACK:                   {                       mqtt_device_connected = TRUE;                   } break;          case PUBACK:                   {                       mIotTcpTxFrame.waitFlag = 0;  //收到回应,继续上报下一条数据                   }  break;          default:                     break;    }         iot_missContactCount = 0;   //有收到数据,则表示保持通讯    pbuf_free(p);         ret_err = ERR_OK;  }  else if (err == ERR_OK)   {    /*进入此处导致tcp关闭。返回的错误值err == ERR_OK 是个什么概念呢?*/mem_free(name);         UdpStdioPrintf("iot_tcp_recv::err== ERR_OK->tcp_close");    return tcp_close(tpcb);  }   return ret_err;}
友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
该问题目前已经被作者或者管理员关闭, 无法添加新回复
5条回答
正点原子
1楼-- · 2019-08-14 22:57
帮顶
浮生若佛
2楼-- · 2019-08-15 01:25
哇,多谢原子哥。好荣幸
浮生若佛
3楼-- · 2019-08-15 06:40
其实我这些初始化基本是参照tcp_client_echo那个例程写的,昨晚想到最原始参照的LwIP-MQTT-Client--Example例程好像不会出现这个问题的,刚刚测试了下,确实几乎不会导致掉线,查看初始化,确实是将返回错误当成是正常情况来处理的,代码如下:
err_tiot_tcp_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
{
    if (err == ERR_OK && p != NULL) {
    //接收并处理数据
    }
    else
    {
        /* No data arrived */
        /* That means the client closes the connection and sent us a packet with FIN flag set to 1. */
        /* We have to cleanup and destroy out TCPConnection. */
            UARTprintf("Connection closed by client. ");
        tcp_close(pcb);
    }
    pbuf_free(p);
    return ERR_OK;
}
上面仅罗列程序的基本框架,很可能我昨天的想的接收函数的返回错误err = ERR_OK就是表示没有发生错误。但小弟还有一事不明,到底什么情况下有可能导致tcp接收到NULL呢?注释里的意思是说“客户端关闭了连接并且发送了一个FIN包过来",这里说的客户端应该是指远端客户端,并不是指本机,而这个例程应该是个服务器初始化的注释。说白了,远端的设备主动关闭或者发生异常发送了一个FIN包过来,我这边收到这个包也关闭TCP连接。
BJTT
4楼-- · 2019-08-15 10:56
 精彩回答 2  元偷偷看……
浮生若佛
5楼-- · 2019-08-15 14:22
服务器我也不懂,我们现在有两个服务器,阿里云和腾讯云。

一周热门 更多>