OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 3112|回复: 5

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

[复制链接]

1

主题

6

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2016-8-10
在线时间
3 小时
发表于 2017-7-31 18:28:45 | 显示全部楼层 |阅读模式
5金钱
通过客户端(手机)控制设备(裸机,无系统),系统架构为手机发送给云服务器,服务器转发给mqtt代理,代理再发送给设备。每按一下按键发送同一条控制指令。在连续按键一段时间后出现tcp断开连接的现象。无论按动的频率多慢,1秒按一次也会掉线;出错时间也不定,有时按到第30多次掉线,有时按到10多次就掉线了。
我在自己电脑上配置了一个mqtt客户端,订阅同一个主题,能正确收到每次按键的控制指令,个人认为客户端下发的指令至少顺利到达mqtt代理,并且mqtt代理也正常的将数据发送出去了,所以问题就只能出在我的设备上。最可能的,我想还应该是tcp初始化的问题。这种判断对吗?
下面是TCP客户端初始化函数,使用的协议栈为lwip 1.4.1,程序都是参照网上的例程修修改改而来,新手接触lwip,让大家见笑了。
出错的地方使用红色字标出,有两个问题我一直不解: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;
}

正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

530

主题

11万

帖子

34

精华

管理员

Rank: 12Rank: 12Rank: 12

积分
165462
金钱
165462
注册时间
2010-12-1
在线时间
2114 小时
发表于 2017-8-1 00:04:58 | 显示全部楼层
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2016-8-10
在线时间
3 小时
 楼主| 发表于 2017-8-1 09:26:31 | 显示全部楼层
哇,多谢原子哥。好荣幸
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2016-8-10
在线时间
3 小时
 楼主| 发表于 2017-8-1 09:50:03 | 显示全部楼层
其实我这些初始化基本是参照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.\r\n");
        tcp_close(pcb);
    }
    pbuf_free(p);
    return ERR_OK;
}
上面仅罗列程序的基本框架,很可能我昨天的想的接收函数的返回错误err = ERR_OK就是表示没有发生错误。但小弟还有一事不明,到底什么情况下有可能导致tcp接收到NULL呢?注释里的意思是说“客户端关闭了连接并且发送了一个FIN包过来",这里说的客户端应该是指远端客户端,并不是指本机,而这个例程应该是个服务器初始化的注释。说白了,远端的设备主动关闭或者发生异常发送了一个FIN包过来,我这边收到这个包也关闭TCP连接。
回复

使用道具 举报

9

主题

141

帖子

1

精华

高级会员

Rank: 4

积分
606
金钱
606
注册时间
2017-1-3
在线时间
65 小时
发表于 2017-8-1 09:52:21 | 显示全部楼层
我现在也在研究这个,想问一下,有什么好用的云服务器可以推荐吗
回复

使用道具 举报

1

主题

6

帖子

0

精华

新手上路

积分
24
金钱
24
注册时间
2016-8-10
在线时间
3 小时
 楼主| 发表于 2017-8-1 09:56:06 | 显示全部楼层
服务器我也不懂,我们现在有两个服务器,阿里云和腾讯云。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-4-20 02:45

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表