STM32的tcp_echoserver例程解说

1.C/S网络程序的工作流程,如图:

2.ST关于TCP的例程分为client和server,根据字面意思,可以知道tcp_echoserver例程是将STM32作为server来用。而例程的第一步呢,便是初始化,调用的是tcp_echoserver_init()函数。

    在tcp_echoserver_init()函数里,主要做了这么几件事情:
     1. 创建一个新的TCP协议控制块
     2. 绑定地址和端口号(port)
     3. 开始监听(listen)
     4. 设置accept的回调函数

    其完整代码如下:

void tcp_echoserver_init(void)  
{  
  //创建一个新的TCP控制块  
  tcp_echoserver_pcb = tcp_new();  
  
  if (tcp_echoserver_pcb != NULL)  
  {  
    err_t err;  
      
    //绑定到端口7  
    err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);  
      
    if (err == ERR_OK)  
    {  
      //开始监听  
      tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);  
        
      //设置tcp_echoserver_accept为accept的回调函数  
      tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);  
    }  
    else   
    {  
      printf("Can not bind pcb\n");  //norains 2011-7-4 comment  
    }  
  }  
  else  
  {  
    printf("Can not create new pcb\n");   //norains 2011-7-4 comment  
  }  
}  

当客户端开始连接之后,那么被设置的tcp_echoserver_accept()回调函数就会被调用。该函数主要是创建一个新的数据结构,并且将该数据结构传递给底层的TCP,最后分别是设置receive,error和poll这三个回调函数。
  
  tcp_echoserver_accept()代码如下所示:

static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)  
{  
  err_t ret_err;  
  struct tcp_echoserver_struct *es;  
  
  LWIP_UNUSED_ARG(arg);  
  LWIP_UNUSED_ARG(err);  
  
  ///给新的连接设置优先级  
  tcp_setprio(newpcb, TCP_PRIO_MIN);  
  
  //分配一个结构体空间以保持TCP的连接  
  es = (struct tcp_echoserver_struct *)mem_malloc(sizeof(struct tcp_echoserver_struct));  
  if (es != NULL)  
  {  
    es->state = ES_ACCEPTED;  
    es->pcb = newpcb;  
    es->p = NULL;  
      
    //传递新分配的结构体数据给新的pcb  
    tcp_arg(newpcb, es);  
      
    //为新的连接设置receive回调函数   
    tcp_recv(newpcb, tcp_echoserver_recv);  
      
    //为新的连接设置error回调函数  
    tcp_err(newpcb, tcp_echoserver_error);  
      
    //为新的连接设置poll回调函数  
    tcp_poll(newpcb, tcp_echoserver_poll, 1);  
      
    ret_err = ERR_OK;  
  }  
  else  
  {  
    /* return memory error */  
    ret_err = ERR_MEM;  
  }  
  return ret_err;    
}  

接下来便是tcp_echoserver_recv()这个回调函数,因为该函数比较大,这里就不再全部罗列代码了。对于使用者来说,只需要知道相应的判定条件来代表什么意思就足够了,如:

static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)  
{  
  struct tcp_echoserver_struct *es;  
  err_t ret_err;  
  
  LWIP_ASSERT("arg != NULL",arg != NULL);  
    
  es = (struct tcp_echoserver_struct *)arg;  
  
  if (p == NULL)  
  {  
   //如果接收到空的帧,则释放连接  
   ...  
  }     
  else if(err != ERR_OK)  
  {  
   //接收到一个非空的帧,但可能某些原因出错,导致返回值不为ERR_OK,故在此释放缓存  
   ...  
  }  
  else if(es->state == ES_ACCEPTED)  
  {  
   //连接成功,在这里需要设置sent回调函数  
   ...  
  }  
  else if (es->state == ES_RECEIVED)  
  {  
   //从客户端收到数据  
   ...  
  }  
  else  
  {  
   //当连接关闭时,还收到了数据  
   ...  
  
  }  
    
  return ret_err;  
}  

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值