RT-Thread论坛
直播中

张虎豹

8年用户 1666经验值
私信 关注
[问答]

ESP8266 socket通信,串口溢出怎么解决?

1、硬件平台:原子精英板 STM32f103zet6+esp8266
   开发板作为client,网络调试助手模拟server
学习研究AT SOCKET有一段时间了,之前逛论坛提问解决了一些问题。遇到的问题如下:

  • 1、at socket关闭不彻底,导致重连server时,socket连接号一直递增。(已解决)
  • 2、socket连接断开,报错 esp0 device socket(0) wait connect result timeout.(已解决)
  • 3、AT Client接收数据失败,串口获取数据提示超时,该问题会在程序运行一段时间后出现,还未找到原因?

    • [E/at_client] AT Client receive failed, uart device get data error(-2)
    • [E/at.skt.esp] esp0 device receive size(24) data failed.


  • 4、程序运行一段时间后,
    提示

    • [W/UART] Warning: There is no enough buffer for saving data, please increase the RT_SERIAL_RB_BUFSZ option.


    论坛里关于这个问题的回答是:增大缓存、及时处理串口数据、降低串口波特率(目前AT串口波特率115200)
    结合调试记录,当出现这个提示后,串口会一直卡在串口中断里,如下图:

针对这个问题,网络调试助手端每隔2秒会下发指令,长度24.目前RT_SERIAL_RB_BUFSZ设置为1024
我觉得增大缓存和降低波特率并不能真正彻底解决问题。还是串口数据处理不及时造成,但我没理解这句话(或者说怎样才算是及时把数据取走了),
client端使用的select方式接收数据,按照个人理解,recv接收数据,不就是把数据取走了吗?至于把数据拿去做什么应该和接收没什么关系了。请问这里该如何理解呢?
这个问题的出现最终会导致client再也连不上server。
我的client开了三个线程,

  • A:socket连接状态判断线程
  • B:接收线程
  • C:发送线程(发送线程里面模拟了心跳)
线程间通信用的event.
代码如下,可否帮忙看下问题出在哪里

  • static rt_thread_t tid25 = RT_NULL;
  • static rt_thread_t rx_tid25 = RT_NULL;
  • static rt_thread_t tx_tid25 = RT_NULL;
  • static rt_event_t socket_event = RT_NULL;

  • //socket接收线程
  • #define CLIENT_THREAD_PRIORITY             25
  • #define CLIENT_THREAD_STACK_SIZE           1024
  • #define CLIENT_THREAD_TIMESLICE            10

  • #define TCPCLIENT_CLOSE     (1 << 0)            //连接关闭
  • #define TCPCLIENT_TX         (1 << 1)            //发送
  • #define TCPCLIENT_PARSE        (1 << 2)            //解析接收数据
  • #define TCPCLIENT_RX_EXIT    (1 << 3)            //退出接收线程
  • #define TCPCLIENT_TX_EXIT    (1 << 4)            //退出发送线程

  • //连接服务器
  • static int tcp_connect1(void)
  • {
  •     struct sockaddr_in server_addr;
  •     struct netdev *netdev = RT_NULL;

  •     int sock = -1;
  •     char svrbuf[16] = "192.168.1.111";
  •     //rt_err_t ret;

  •     // 通过名称获取 netdev 网卡对象 */
  •     netdev = netdev_get_by_name("esp0");
  •     if (netdev == RT_NULL)
  •     {
  •         LOG_E("get network interface device(%s) failed.", "esp0");
  •     }

  •     // 设置默认网卡对象 */
  •     netdev_set_default(netdev);

  •     // 初始化预连接的服务端地址 */
  •     server_addr.sin_family = AF_AT;
  •     server_addr.sin_port = htons(MySysSet.svrPort); //8887
  •     sprintf(svrbuf,"%d.%d.%d.%d",MySysSet.svrIp[0],MySysSet.svrIp[1],MySysSet.svrIp[2],MySysSet.svrIp[3]);//192.168.1.104
  •     server_addr.sin_addr.s_addr = inet_addr(svrbuf);
  •     rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));

  • RECONNETC:
  •     rt_thread_mdelay(500);
  •     // 创建一个socket,类型是SOCKET_STREAM,TCP类型 */
  •     if ((sock = socket(AF_AT, SOCK_STREAM, 0)) == -1)
  •     {
  •         /* 创建socket失败 */
  •         LOG_E("Socket create error!");
  •         goto RECONNETC;
  •     }
  •     LOG_I("Socket (%d) create success!", sock);

  •     // 连接到服务端 */
  •     if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
  •     {
  •         // 连接失败 */
  •         LOG_E("Connect server fail!");
  •         closesocket(sock);
  •         goto RECONNETC;
  •     }
  •     LOG_I("Client connect Server success.");

  •     return sock;
  • }

  • // 接收线程入口函数 */
  • static void tcp_rx_thread(void *parameter)
  • {
  •     uint16_t calcCRC,recvCRC;//接收的校验码
  •     int maxfdp1;
  •     int rc = 0;
  •     int ret;
  •     fd_set readset;

  •     // 获取需要监听的描述符号最大值 */
  •     maxfdp1 = socketfd + 1;

  •     while(1)
  •     {
  •         // 清空可读事件描述符列表 */
  •         FD_ZERO(&readset);
  •         // 将需要监听可读事件的描述符加入列表 */
  •         FD_SET(socketfd,&readset);

  •         // 获取需要监听的描述符号最大值 */
  •         //maxfdp1 = socketfd+1;

  •         // 等待设定的网络描述符有事件发生 */
  •         rc = select(maxfdp1,&readset,0,0,0);
  •         // 至少有一个文件描述符有指定事件发生再向后运行 */
  •         if(rc == 0)        continue;

  •         // 查看 sock 描述符上有没有发生可读事件 */
  •         if (FD_ISSET(socketfd, &readset))
  •         {
  •             // 从sock连接中接收最大BUFSZ - 1字节数据 */
  •             rx_len = recv(socketfd, recv_data, BUFSZ - 1, 0);

  •             if (rx_len <= 0)
  •             {
  •                 if(!(errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN))
  •                 {
  •                     LOG_E("recv error!");
  •                     //关闭socket
  •                     ret = closesocket(socketfd);
  •                     if (ret == 0)
  •                     {
  •                         LOG_W("rx closed socketfd (%d) success",socketfd);
  •                         socketfd = -1;
  •                     }
  •                     rt_event_send(socket_event, TCPCLIENT_CLOSE);
  •                     break;
  •                 }
  •             }
  •             else
  •             {
  •                 // 有接收到数据,把末端清零 */
  •                 recv_data[rx_len] = '�';
  •                 //解析数据,成功后通知发送
  •                 rt_event_send(socket_event, TCPCLIENT_TX);
  •             }
  •         }
  •         rt_thread_mdelay(50);
  •     }
  • }

  • // 发送线程入口函数 */
  • static void tcp_tx_thread(void *parameter)
  • {
  •     int ret;
  •     const char *str = "alive test";
  •     while(1)
  •     {
  •         if (rt_event_recv(socket_event, TCPCLIENT_TX, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 30000, RT_NULL) == RT_EOK)
  •         {
  •             ret = send(socketfd, send_data, tx_len, 0);
  •             if (ret <= 0)    //发送出错
  •             {
  •                 //发送失败
  •                 LOG_E("data send error.");
  •                 //关闭socket
  •                 ret = closesocket(socketfd);
  •                 if (ret == 0)
  •                 {
  •                     LOG_W("tx1 closed socketfd (%d) success",socketfd);
  •                     socketfd = -1;
  •                 }
  •                 rt_event_send(socket_event, TCPCLIENT_CLOSE);
  •                 break;
  •             }
  •         }
  •         else    //心跳包
  •         {
  •             ret = send(socketfd, str, strlen(str), 0);
  •             if (ret <= 0)    //发送出错
  •             {
  •                 //发送失败
  •                 LOG_E("keepalive send error.");
  •                 ret = closesocket(socketfd);
  •                 if (ret == 0)
  •                 {
  •                     LOG_W("tx2 closed socketfd (%d) success",socketfd);
  •                     socketfd = -1;
  •                 }
  •                 rt_event_send(socket_event, TCPCLIENT_CLOSE);
  •                 break;
  •             }
  •         }
  •         rt_thread_mdelay(40);
  •     }
  • }

  • //判断连接状态线程
  • static void client_connect_state(void *parameter)
  • {
  •     //rt_err_t  result;
  • RECONNECT:
  •     socketfd = tcp_connect1();
  •     if(socketfd != -1 )
  •     {
  •         //创建数据发送线程,优先级25
  •         tx_tid25 = rt_thread_create("client_tx", tcp_tx_thread, RT_NULL,
  •                                         CLIENT_THREAD_STACK_SIZE,
  •                                         CLIENT_THREAD_PRIORITY,
  •                                         CLIENT_THREAD_TIMESLICE);
  •         // 如果获得线程控制块,启动这个线程 */
  •         if (tx_tid25 != RT_NULL)
  •         {
  •             LOG_I("create Client_tx_thread success");
  •             rt_thread_startup(tx_tid25);
  •         }

  •         //创建接收线程,优先级24
  •         rx_tid25 = rt_thread_create("client_rx", tcp_rx_thread, RT_NULL,
  •                                         CLIENT_THREAD_STACK_SIZE,
  •                                         CLIENT_THREAD_PRIORITY-1,
  •                                         CLIENT_THREAD_TIMESLICE);
  •         // 如果获得线程控制块,启动这个线程 */
  •         if (rx_tid25 != RT_NULL)
  •         {
  •             LOG_I("create Client_rx_thread success");
  •             rt_thread_startup(rx_tid25);
  •         }
  •     }
  •     while(1)
  •     {
  •         if (rt_event_recv(socket_event, TCPCLIENT_CLOSE, RT_EVENT_FLAG_OR | RT_EVENT_FLAG_CLEAR, 10000, RT_NULL) == RT_EOK)
  •         {
  •             //删除线程
  •             if( rt_thread_delete(rx_tid25) == RT_EOK )
  •                 LOG_D("client_rx_thread Delete OK");
  •             rt_thread_mdelay(250);
  •             goto RECONNECT;
  •         }
  •         rt_thread_mdelay(50);
  •     }
  • }

  • //创建线程
  • int fnUserClient(void)
  • {
  •     //
  •     socket_event = rt_event_create("sock_event", RT_IPC_FLAG_FIFO);
  •     if (socket_event == RT_NULL)
  •     {
  •         LOG_E("tcpclient socket event create failed");
  •     }
  •     LOG_D("tcpclient socket event create ok");

  •     //创建线程,优先级23
  •     tid25 = rt_thread_create("cli2svr",
  •                                 client_connect_state,
  •                                 RT_NULL,
  •                                 CLIENT_THREAD_STACK_SIZE,
  •                                 CLIENT_THREAD_PRIORITY-2,
  •                                 CLIENT_THREAD_TIMESLICE);
  •     // 如果获得线程控制块,启动这个线程 */
  •     if (tid25 != RT_NULL)
  •     {
  •         rt_thread_startup(tid25);
  •     }
  •     else
  •     {
  •         LOG_E("create Client_thread failed");
  •         return -1;
  •     }
  •     return 0;
  • }




更多回帖

发帖
×
20
完善资料,
赚取积分