分享

lwip raw tcp/client 实现

 心不留意外尘 2016-06-24
http://blog.csdn.net/shaohuazuo/article/details/39159635
2014

  1. stm32 lwip tcp客户端和服务端编写。  
  2.   
  3.   
  4. lwip提供的各种回调函数  
  5.   
  6. 1.tcp_new()函数:  
  7.     用来返回一个struct tcp_pcb* 的一个指针。  
  8.   
  9. 2.设置tcp/ip的保活设置。  
  10.      client_pcb->so_options |= SOF_KEEPALIVE;  
  11.          client_pcb->keep_idle = 50000;     // ms   tcp连接上5秒之后,发送第一keep_alive数据包。  
  12.          client_pcb->keep_intvl = 20000;   // ms   以后每隔2秒发送一个keep_alive数据包。  
  13.          client_pcb->keep_cnt = 5;      // 如果联系5次没有收到对方回应的keep_alive数据包。则认为已经断开连接。  
  14.   
  15. 3. err_t tcp_connect(struct tcp_pcb *pcb, struct ip_addr *ipaddr, u16_t port,  
  16.       err_t (* connected)(void *arg, struct tcp_pcb *tpcb, err_t err))  
  17.   
  18.     函数功能:  
  19.         用来连接到一个指定的tcp服务端。  
  20.   
  21.     参数一:  
  22.         tcp_new()函数的返回值。作为该函数的第一参数。  
  23.       
  24.     参数二:  
  25.         要连接到那个ip地址上,可以使用下面的这个宏函数进行处理。  
  26.           
  27.         IP4_ADDR( &DestIPaddr, *destip, *(destip+1),*(destip+2), *(destip+3));  
  28.   
  29.         #define IP4_ADDR(ipaddr, a,b,c,d) \  
  30.         (ipaddr)->addr = htonl(((u32_t)((a) & 0xff) << 24) | \  
  31.                                ((u32_t)((b) & 0xff) << 16) | \  
  32.                                ((u32_t)((c) & 0xff) << 8) | \  
  33.                                 (u32_t)((d) & 0xff))  
  34.     参数三:连接到tcp服务端的端口号  2000,  
  35.       
  36.     参数四:它是一个函数指针。这个函数指针说明在tcp连接上服务端之后,会调用该函数。  
  37.   
  38.   
  39. 4.void tcp_err(struct tcp_pcb *pcb, void (* errf)(void *arg, err_t err))  
  40.       
  41.     函数的功能:  
  42.         连接出错的时候。进行错误处理的函数。  
  43.     参数一:  
  44.         用来描述tcp连接的一个结构体。  
  45.     参数二:  
  46.         用来处理错误的函数。当连接出现异常的时候。会调用这个函数。  
  47.   
  48. 5.void tcp_arg(struct tcp_pcb *pcb, void *arg)  
  49.     功能:  
  50.         提供一种可以让应用程序传递参数给回调函数的方法。  
  51.     参数一:  
  52.         用来描述tcp连接的一个结构体。  
  53.     参数二:  
  54.         应用程序提供的一个结构体。他可以保护tcp的状态,或者tcp要发送的数据等信息。  
  55.   
  56. 6.static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)  
  57.     函数功能:  
  58.         当接收到数据的时候。对接收的数据进行处理。  
  59.     参数一:  
  60.         该参数是通过tcp_arg()函数传入的。  
  61.     参数二:   
  62.         用来描述tcp连接的一个结构体。  
  63.     参数三:  
  64.         接收到的数据都存放在这个pbuf中。  
  65.     参数四:  
  66.         err,它说明了这次tcp连接过程中是否出现异常。如果他的值为ERR_OK说明正常。  
  67.       
  68.     注释:如果接收到的 p 等于空的话。说明服务端主动关闭连接了,那么需要关闭这个socket,连接。  
  69.     并启动一个time。定时的重新连接服务端socket.  
  70.   
  71. 7. void tcp_recved(struct tcp_pcb *pcb, u16_t len)  
  72.     函数功能:  
  73.     当tcp_client_recv()函数调用正常的话。则可用使用该方法进行数据接收方法。  
  74.     参数一:  
  75.         用来描述tcp连接的一个结构体。  
  76.     参数二:  
  77.         要接收的数据长度。一般情况下可以认为是p->tot_len。  
  78.   
  79.       
  80.   
  81. 最后把函数代码该贴上。  
  82. err_t tcp_client_connect(const uint8_t *destip, uint16_t port)  
  83. {  
  84.   struct tcp_pcb *client_pcb;  
  85.   struct ip_addr DestIPaddr;  
  86.   err_t err = ERR_OK;  
  87.   
  88.   /* create new tcp pcb */  
  89.   client_pcb = tcp_new();  
  90.   client_pcb->so_options |= SOF_KEEPALIVE;  
  91.  #if 1  
  92.   client_pcb->keep_idle = 50000;    // ms  
  93.   client_pcb->keep_intvl = 20000;       // ms  
  94.   client_pcb->keep_cnt = 5;   
  95.  #endif      
  96.   if (client_pcb != NULL)  
  97.   {  
  98.   
  99.      
  100.    IP4_ADDR( &DestIPaddr, *destip, *(destip+1),*(destip+2), *(destip+3) );  
  101.   
  102.     /* connect to destination address/port */  
  103.     err = tcp_connect(client_pcb,&DestIPaddr,port,tcp_client_connected);  
  104.      
  105.     tcp_err(client_pcb,tcp_errf);  
  106.       
  107.   }  
  108.   return err;  
  109.     
  110. }  
  111.   
  112.   
  113. static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)  
  114. {  
  115.      
  116.     if(es == NULL) es = (struct client *)mem_malloc(sizeof(struct client));  
  117.     switch(err){  
  118.         case ERR_OK:    
  119.           es->pcb = tpcb;                                  /*设置当前的状态为连接状态?*/    
  120.           es->p_tx = NULL;  
  121.           es->state = ES_CONNECTED;    
  122.           tcp_arg(tpcb, es);                       /*把当前的参数传给所有的回调函数?   */   
  123.           tcp_recv(tpcb, tcp_client_recv);  
  124.           
  125.           break ;  
  126.        case ERR_MEM :  
  127.            tcp_client_connection_close(tpcb, es);                  
  128.           break ;  
  129.        default :  
  130.            break ;  
  131.              
  132.    }  
  133.    return err;  
  134. }  
  135.   
  136.   
  137. static void tcp_errf(void *arg,err_t err){  
  138.     printf("\r\ntcp_errf be called...\r\n");  
  139.     if(es == NULL){  
  140.         es = (struct client *)mem_malloc(sizeof(struct client));  
  141.         es = (struct client *)arg;  
  142.     }  
  143.     if(err == ERR_OK ){  
  144.           /* No error, everything OK. */  
  145.           return ;  
  146.      }     
  147.     switch(err)  
  148.     {   
  149.         case ERR_MEM:                                            /* Out of memory error.     */  
  150.             printf("\r\n ERR_MEM   \r\n");  
  151.             break;    
  152.         case ERR_BUF:                                            /* Buffer error.            */  
  153.             printf("\r\n ERR_BUF   \r\n");  
  154.             break;  
  155.         case  ERR_TIMEOUT:                                       /* Timeout.                 */  
  156.             printf("\r\n ERR_TIMEOUT   \r\n");  
  157.             break;  
  158.         case ERR_RTE:                                            /* Routing problem.         */        
  159.              printf("\r\n ERR_RTE   \r\n");  
  160.             break;  
  161.        case ERR_ISCONN:                                          /* Already connected.       */  
  162.              printf("\r\n ERR_ISCONN   \r\n");  
  163.             break;  
  164.         case ERR_ABRT:                                           /* Connection aborted.      */  
  165.             printf("\r\n ERR_ABRT   \r\n");  
  166.             break;  
  167.         case ERR_RST:                                            /* Connection reset.        */       
  168.             printf("\r\n ERR_RST   \r\n");  
  169.             break;  
  170.         case ERR_CONN:                                           /* Not connected.           */  
  171.           printf("\r\n ERR_CONN   \r\n");  
  172.             break;  
  173.         case ERR_CLSD:                                           /* Connection closed.       */  
  174.             printf("\r\n ERR_CLSD   \r\n");  
  175.             break;  
  176.         case ERR_VAL:                                            /* Illegal value.           */  
  177.            printf("\r\n ERR_VAL   \r\n");  
  178.            return;  
  179.         case ERR_ARG:                                            /* Illegal argument.        */  
  180.             printf("\r\n ERR_ARG   \r\n");  
  181.             return;  
  182.         case ERR_USE:                                            /* Address in use.          */  
  183.            printf("\r\n ERR_USE   \r\n");  
  184.            return;   
  185.         case ERR_IF:                                             /* Low-level netif error    */  
  186.             printf("\r\n ERR_IF   \r\n");  
  187.             break;  
  188.         case ERR_INPROGRESS:                                     /* Operation in progress    */  
  189.             printf("\r\n ERR_INPROGRESS   \r\n");  
  190.             break;  
  191.   
  192.     }  
  193.    es->state  = ES_CLOSING;  
  194.    err_process();  
  195. }  
  196.       
  197.       
  198. /** 
  199.   * @brief tcp_receiv callback 
  200.   * @param arg: argument to be passed to receive callback  
  201.   * @param tpcb: tcp connection control block  
  202.   * @param err: receive error code  
  203.   * @retval err_t: retuned error   
  204.   */  
  205. static err_t tcp_client_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)  
  206. {   
  207.   struct client *es;  
  208.   err_t ret_err;  
  209.   LWIP_ASSERT("arg != NULL",arg != NULL);  
  210.   es = (struct client *)arg;  
  211.   if (p == NULL)  
  212.   {  
  213.     /* remote host closed connection */  
  214.     es->state = ES_CLOSING;  
  215.     if(es->p_tx == NULL)  
  216.     {  
  217.        /* we're done sending, close connection */  
  218.        tcp_client_connection_close(tpcb, es);  
  219.     }  
  220.     ret_err = ERR_OK;  
  221.   }     
  222.   else if(err != ERR_OK)  
  223.   {  
  224.     /* free received pbuf*/  
  225.     if (p != NULL)  
  226.     {  
  227.       pbuf_free(p);  
  228.     }  
  229.     ret_err = err;  
  230.   }  
  231.   else if(es->state == ES_CONNECTED)  
  232.   {    
  233.     /* Acknowledge data reception */  
  234.     tcp_recved(tpcb, p->tot_len);                   //获取p中的数据。  
  235.   
  236.     memset(recevRxBufferTcpEth,0x00,TCPREVDATALEN);  
  237.     if(p->len > TCPREVDATALEN){      
  238.         p->len= TCPREVDATALEN;      
  239.     }  
  240.     memcpy(&recevRxBufferTcpEth,p->payload,p->len);  
  241.     tcpRecevieFlag  = 1;                    //将tcp设置为1.说明接收到了服务端的数据。  
  242.     pbuf_free(p);                     
  243.     ret_err = ERR_OK;     
  244.   }  
  245.   /* data received when connection already closed */  
  246.   else  
  247.   {  
  248.     /* Acknowledge data reception */  
  249.     tcp_recved(tpcb, p->tot_len);  
  250.       
  251.     /* free pbuf and do nothing */  
  252.     pbuf_free(p);  
  253.     ret_err = ERR_OK;  
  254.   }  
  255.   return ret_err;  
  256. }  
  257.   
  258.   
  259. /** 
  260.   * @brief function used to send data 
  261.   * @param  tpcb: tcp control block 
  262.   * @param  es: pointer on structure of type client containing info on data  
  263.   *             to be sent 
  264.   * @retval None  
  265.   */  
  266. void tcp_client_send(struct tcp_pcb *tpcb, struct client * es)  
  267. {  
  268.   struct pbuf *ptr;  
  269.   err_t wr_err = ERR_OK;   
  270.   while ((wr_err == ERR_OK) &&  
  271.          (es->p_tx != NULL) &&   
  272.          (es->p_tx->len <= tcp_sndbuf(tpcb)))  
  273.   {  
  274.     /* get pointer on pbuf from es structure */  
  275.     ptr = es->p_tx;  
  276.   
  277.     wr_err = tcp_write(tpcb, ptr->payload, ptr->len, 1);  
  278.       
  279.     if (wr_err == ERR_OK)  
  280.     {   
  281.       /* continue with next pbuf in chain (if any) */  
  282.       es->p_tx = ptr->next;  
  283.         
  284.       if(es->p_tx != NULL)  
  285.       {  
  286.       /* increment reference count for es->p */  
  287.         pbuf_ref(es->p_tx);  
  288.       }  
  289.       pbuf_free(ptr);  
  290.    }  
  291.    else if(wr_err == ERR_MEM)  
  292.    {  
  293.       /* we are low on memory, try later, defer to poll */  
  294.      es->p_tx = ptr;                                                      
  295.    }  
  296.    else  
  297.    {  
  298.      es->p_tx = ptr;      
  299.      /* other problem ?? */  
  300.    }  
  301.   }  
  302. }  
  303.   
  304.   
  305. //user send message   
  306. u8_t tcp_send_message(void *msg, uint16_t len){  
  307.     u8_t  count = 0;  
  308.     struct pbuf *p;    
  309.     if(es->state != ES_CONNECTED)  return -1;  
  310.     if(es->p_tx == NULL){  
  311.           
  312.           es->p_tx  = pbuf_alloc(PBUF_TRANSPORT,len,PBUF_RAM);            
  313.           pbuf_take( es->p_tx , (char*)msg, len);  
  314.     }  
  315.     tcp_client_send(es->pcb,es);  
  316.     return 1;  
  317. }  
  318.   
  319.   
  320.   
  321.   
  322. /** 
  323.   * @brief This function is used to close the tcp connection with server 
  324.   * @param tpcb: tcp connection control block 
  325.   * @param es: pointer on client structure 
  326.   * @retval None 
  327.   */  
  328. static void tcp_err_close()  
  329. {  
  330.   /* remove callbacks */  
  331.   tcp_recv(es->pcb, NULL);  
  332.     
  333.   if (es != NULL)  
  334.   {  
  335.     if(es->p_tx != NULL){  
  336.         pbuf_free(es->p_tx);  
  337.     }  
  338.     if (es->pcb != NULL) {  
  339.          tcp_close(es->pcb);  
  340.     }  
  341.     mem_free(es);  
  342.   }  
  343. }  
  344.   
  345.   
  346. static void tcp_client_connection_close()  
  347. {  
  348.   /* remove callbacks */  
  349.   tcp_recv(es->pcb, NULL);  
  350.   if (es != NULL)  
  351.   {  
  352.     if(es->p_tx != NULL){  
  353.         pbuf_free(es->p_tx);  
  354.     }  
  355.     if (es->pcb != NULL) {  
  356.           /* close tcp connection */  
  357.          tcp_close(es->pcb);  
  358.     }  
  359.     mem_free(es);  
  360.     es = NULL;  
  361.   }  
  362.   set_timer4_countTime(TIMER_5000MS);  
  363. }  
  364.   
  365. //错误处理函数。当tcp连接发送错误的时候。调用该函数。  
  366. static void err_process(){  
  367.     connet_flag++;  
  368.      if(connet_flag<= 3){  
  369.         set_timer4_countTime(TIMER_5000MS);  
  370.      }  
  371.      if(connet_flag>3){       
  372.          connet_flag = 4;  
  373.         set_timer4_countTime(TIMER_10000MS);  
  374.      }  
  375. }  
  376. //定时时间到的时候。调用该方法重连。  
  377. void reconnet_tcp_timer(){  
  378.      if(es != NULL){  
  379.         tcp_err_close(es->pcb, es );  
  380.         tcp_client_connect(ip_des,destcp_port);  
  381.      }else{  
  382.         tcp_client_connect(ip_des,destcp_port);  
  383.      }    
  384. }  
  385.  //用来处理数据的方法,具体的业务数据。  
  386. int W301ProcessRecvTcpData(){  
  387.     
  388. }  

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多