搜索
bottom↓
回复: 4

请教ffxz 关于TCP客户端的问题

[复制链接]

出0入0汤圆

发表于 2014-6-24 13:30:53 | 显示全部楼层 |阅读模式
请教ffxz:用RTT系统的lwip做客户端,如果服务器不开启监听,客户端就需要一直去尝试连接,假设几秒钟就重新尝试连接一次,
就这样一直工作 会不会出现死机?我现在用裸机做的lwip客户端,收发数据都正常,如果服务器开启监听下一切都正常,无意中
发现关闭服务器后几分钟系统就死机了,在这个帖子里http://www.amobbs.com/thread-5585584-1-1.html,内存出问题了,
如果RTT下没有这样的问题,我想换成RTT系统来做。

阿莫论坛20周年了!感谢大家的支持与爱护!!

一只鸟敢站在脆弱的枝条上歇脚,它依仗的不是枝条不会断,而是自己有翅膀,会飞。

出0入0汤圆

发表于 2014-6-24 15:33:56 | 显示全部楼层
你是不是没释放socket?这个和RT-Thread无关,你这样的代码在裸机上有问题,在RT-Thread上也可能会有问题。

出0入0汤圆

 楼主| 发表于 2014-6-24 15:57:26 | 显示全部楼层
我是用TCP做的 没有用socket函数,只要没连接上,tcp_err函数会打印错误状态 ERR_ABRT和ERR_RST,然后就执行tcp_close,在这个函数里会释放内存的,
代码流程比较简单的,应该很好看明白

/***********************************************************************
函数名称:client_data_process(void)
功    能:客户端数据处理函数
***********************************************************************/
//client_data_process函数放在主循环while(1)里,系统tick每隔250ms调取一次,
void client_data_process(void)
{
        const char content[] = "Hello, PC!\r\n";
//client_err==0 未初始化成功; client_err == 1 连接错误; client_err==2 初始化成功;
  if(client_err < 2)
  {
                use_err++;
    if(use_err > 12)//客户端如果不能正常初始化,每隔250ms*12=3秒重新初始化
    {
                        use_err=0;
      tcp_client_init();
                        //led_on(1);      
                        UART0_SendString("Retry connect every 3s\r\n",sizeof("Retry connect every 3s\r\n"));
    }        
  }
  else if(client_err == 2)//客户端正常连接,每隔250ms*4=1s向PC服务器发送数据
  {
                Send_Time++;
    /*if((client_pcb->state == ESTABLISHED) && (Send_Time>=4))
    {
                        //tcp_write(client_pcb, content, sizeof(content), TCP_WRITE_FLAG_COPY);                       
                        UART0_SendString("Hello, PC!\r\n",sizeof("Hello, PC!\r\n"));
                        //led_on(2);
      Send_Time = 0;
    }*/
    if(Send_Time>=4)//每隔1秒钟打印一次client pcb的状态
    {                   
                  switch(client_pcb->state)
                  {
                                 case CLOSED:      UART0_SendStr("0  CLOSED\r\n");     break;
                           case LISTEN:      UART0_SendStr("1  LISTEN\r\n");     break;
                           case SYN_SENT:    UART0_SendStr("2  SYN_SENT\r\n");   break;
                           case SYN_RCVD:    UART0_SendStr("3  SYN_RCVD\r\n");   break;
                           case ESTABLISHED: UART0_SendStr("4  ESTABLISHED\r\n");break;
                           case FIN_WAIT_1:  UART0_SendStr("5  FIN_WAIT_1\r\n"); break;
                           case FIN_WAIT_2:  UART0_SendStr("6  FIN_WAIT_2\r\n"); break;
                           case CLOSE_WAIT:  UART0_SendStr("7  CLOSE_WAIT\r\n"); break;
                           case CLOSING:     UART0_SendStr("8  CLOSING\r\n");    break;
                           case LAST_ACK:    UART0_SendStr("9  LAST_ACK\r\n");   break;
                           case TIME_WAIT:   UART0_SendStr("10 TIME_WAIT\r\n");  break;
                  }
                        tcp_write(client_pcb, content, sizeof(content), TCP_WRITE_FLAG_COPY);
                        UART0_SendString("Hello, PC!\r\n",sizeof("Hello, PC!\r\n"));
                        //led_on(2);
      Send_Time = 0;
    }
        }
}
/***********************************************************************
函数名称:static void tcp_client_err(void *arg, err_t err)
功    能:连接错误时处理的回调函数
***********************************************************************/
static void tcp_client_err(void *arg, err_t err)
{
  switch(err)
  {
                case ERR_OK:    UART0_SendStr("0   ERR_OK\r\n");  break;      
    case ERR_MEM:   UART0_SendStr("-1  ERR_MEM\r\n"); break;
    case ERR_BUF:   UART0_SendStr("-2  ERR_BUF\r\n"); break;
    case ERR_TIMEOUT: UART0_SendStr("-3  ERR_TIMEOUT\r\n"); tcp_close(client_pcb); client_err=1;break;
    case ERR_RTE:   UART0_SendStr("-4  ERR_RTE\r\n"); break;
    case ERR_ABRT:  UART0_SendStr("-5  ERR_ABRT\r\n");      tcp_close(client_pcb); client_err=1; break;
    case ERR_RST:   UART0_SendStr("-6  ERR_RST\r\n");       tcp_close(client_pcb); client_err=1; break;
    case ERR_CLSD:  UART0_SendStr("-7  ERR_CLSD\r\n");      tcp_close(client_pcb); client_err=0; break;
    case ERR_CONN:  UART0_SendStr("-8  ERR_CONN\r\n");      tcp_close(client_pcb); client_err=0; break;
    case ERR_VAL:   UART0_SendStr("-9  ERR_VAL\r\n");    break;
    case ERR_ARG:   UART0_SendStr("-10 ERR_ARG\r\n");    break;
    case ERR_USE:   UART0_SendStr("-11 ERR_USE\r\n");    break;
    case ERR_IF:    UART0_SendStr("-12 ERR_IF\r\n");     break;
    case ERR_ISCONN: UART0_SendStr("-13 ERR_ISCONN\r\n");break;
    case ERR_INPROGRESS: UART0_SendStr("-14 ERR_INPROGRESS\r\n");break;
  }
  switch(client_pcb->state)
  {
                case CLOSED:      UART0_SendStr("0  CLOSED\r\n");     tcp_close(client_pcb); client_err=0;  break;
    case LISTEN:      UART0_SendStr("1  LISTEN\r\n");     break;
    case SYN_SENT:    UART0_SendStr("2  SYN_SENT\r\n");   break;
    case SYN_RCVD:    UART0_SendStr("3  SYN_RCVD\r\n");   break;
    case ESTABLISHED: UART0_SendStr("4  ESTABLISHED\r\n");break;
    case FIN_WAIT_1:  UART0_SendStr("5  FIN_WAIT_1\r\n"); break;
    case FIN_WAIT_2:  UART0_SendStr("6  FIN_WAIT_2\r\n"); break;
    case CLOSE_WAIT:  UART0_SendStr("7  CLOSE_WAIT\r\n"); break;
    case CLOSING:     UART0_SendStr("8  CLOSING\r\n");    break;
    case LAST_ACK:    UART0_SendStr("9  LAST_ACK\r\n");   break;
    case TIME_WAIT:   UART0_SendStr("10 TIME_WAIT\r\n");  break;
  }        
}

void tcp_client_init(void)
{
  struct ip_addr DestIPaddr;
        client_err = 0;//只要进入初始化重新清零
  client_pcb = tcp_new();   
  if (client_pcb != NULL)
  {
    IP4_ADDR( &DestIPaddr, 10, 16, 4, 26 );//写远程服务器IP
    tcp_bind(client_pcb, IP_ADDR_ANY, 4080);//绑定开发板IP和端口号 客户端的端口号随机,也可不配置
                if(tcp_connect(client_pcb,&DestIPaddr,8080,tcp_client_connected) == ERR_OK)
    {                       
      UART0_SendStr("client_err = 2\r\n");       
                        UART0_SendString("The tcp_client_init OK\r\n",sizeof("The tcp_client_init OK\r\n"));
    }        
    else        
    {      
      client_err = 0;//未初始化成功               
                        UART0_SendString("The tcp_client_init not OK\r\n",sizeof("The tcp_client_init not OK\r\n"));
    }
    tcp_err(client_pcb, tcp_client_err);
  }
}

static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{
  struct client *es = NULL;
  const char content[] = "This is Tcp_Client\r\n";
  if (err == ERR_OK)   
  {
          client_err = 2;//初始化成功,进入了回调函数
    es = (struct client *)mem_malloc(sizeof(struct client));  
    if (es != NULL)
    {
      es->state = ES_CONNECTED;
      es->pcb = tpcb;
      es->p_tx = pbuf_alloc(PBUF_TRANSPORT, strlen((char*)data) , PBUF_POOL);         
      if (es->p_tx)
      {
        pbuf_take(es->p_tx, (char*)data, strlen((char*)data));
        tcp_arg(tpcb, es);
        tcp_recv(tpcb, tcp_client_recv);        
        tcp_poll(tpcb, tcp_client_poll, 1);
        
                                UART0_SendString("This is Tcp_Client\r\n",sizeof("This is Tcp_Client\r\n"));
                                tcp_write(tpcb, content, sizeof(content), TCP_WRITE_FLAG_COPY);
                                tcp_err(tpcb, tcp_client_err);
                       
        return ERR_OK;
      }
    }
    else
    {
      /* close connection */
      tcp_client_connection_close(tpcb, es);
                        client_err=1;                       
      /* return memory allocation error */
      return ERR_MEM;  
    }
  }
  else
  {
    /* close connection */
    tcp_client_connection_close(tpcb, es);
    client_err=1;
  }       
  return err;
}

出0入0汤圆

 楼主| 发表于 2014-6-24 16:03:05 | 显示全部楼层
ffxz 发表于 2014-6-24 15:33
你是不是没释放socket?这个和RT-Thread无关,你这样的代码在裸机上有问题,在RT-Thread上也可能会有问题。 ...

我知道你的意思,但是我现在做的不是应用程序的,只是简单的tcp_new --IP4_ADDR--tcp_connect--tcp_client_connected这样一个基本的流程,
RTT的代码我也下载看过,但是都没有做重新连接,真正应用的时候,服务器经常是断电的 不一定都会一直开启,我是问你有没有试验过,将服务器
断开,然后客户端一直无限次尝试连接,直到检测到服务器开机了,连接成功,这样的情况下不出现死机。

出0入0汤圆

 楼主| 发表于 2014-6-24 16:07:32 | 显示全部楼层
我的流程框架是死在内存分配的问题上,因为一直tcp_new,然后不成功 tcp_close,可能某些时候tcp_close函数里的mem_free出错了,然后又重新分配内存,
这个内存就是出错的那个内存,但是我单步调试不知道怎么去追踪,用RTT系统 说是在动态内存方面有两种管理,可能不会出现我说的这种错误吧 能帮忙验证下吗?多谢
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-5-20 00:55

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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