[STM32F2] STM32F2xx的tcp_echoserver例程解说

[复制链接]
 楼主| 598330983 发表于 2017-1-14 10:49 | 显示全部楼层 |阅读模式

//=====================================================================
//TITLE:
//    STM32F2xx的tcp_echoserver例程解说
//AUTHOR:
//    norains
//DATE:
//    Monday  04-July-2011
//Environment:
//    Keil MDK 4.2
//    STM32F207 核心版
//=====================================================================

     最近拿到STM32F207的核心版,板载有网卡芯片,自然要拿过来捣鼓一番。而对于一个从未接触过网络的菜鸟来说,最好的入门方式就是揣测ST公司的例程,所以今天norains也不例外。那么我们就一起来看看这个官方的例程吧!

    首先我们来了解C/S网络程序的工作流程,如图:



    这个图并不是norains所绘制的,而是网上流传的一个名为《TCP/IP Socket网络编程》的PPT所截取的。这个流程各位一定要熟悉,因为接下来所描述的例子流程,和该图例非常吻合。

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

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

    其完整代码如下:

  1. void tcp_echoserver_init(void)
  2. {
  3.   //创建一个新的TCP控制块
  4.   tcp_echoserver_pcb = tcp_new();

  5.   if (tcp_echoserver_pcb != NULL)
  6.   {
  7.     err_t err;
  8.    
  9.     //绑定到端口7
  10.     err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);
  11.    
  12.     if (err == ERR_OK)
  13.     {
  14.       //开始监听
  15.       tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);
  16.       
  17.       //设置tcp_echoserver_accept为accept的回调函数
  18.       tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
  19.     }
  20.     else
  21.     {
  22.       printf("Can not bind pcb\n");  //norains 2011-7-4 comment
  23.     }
  24.   }
  25.   else
  26.   {
  27.     printf("Can not create new pcb\n");   //norains 2011-7-4 comment
  28.   }
  29. }


 楼主| 598330983 发表于 2017-1-14 11:03 | 显示全部楼层
本帖最后由 598330983 于 2017-1-14 11:10 编辑

   当客户端开始连接之后,那么被设置的tcp_echoserver_accept()回调函数就会被调用。该函数主要是创建一个新的数据结构,并且将该数据结构传递给底层的TCP,最后分别是设置receive,error和poll这三个回调函数。
  
  tcp_echoserver_accept()代码如下所示:
  1.   static err_t tcp_echoserver_accept(void *arg, struct tcp_pcb *newpcb, err_t err)
  2.   {
  3.     err_t ret_err;
  4.     struct tcp_echoserver_struct *es;
  5.   
  6.     LWIP_UNUSED_ARG(arg);
  7.     LWIP_UNUSED_ARG(err);
  8.   
  9.     ///给新的连接设置优先级
  10.     tcp_setprio(newpcb, TCP_PRIO_MIN);
  11.   
  12.     //分配一个结构体空间以保持TCP的连接
  13.     es = (struct tcp_echoserver_struct *)mem_malloc(sizeof(struct tcp_echoserver_struct));
  14.     if (es != NULL)
  15.     {
  16.       es->state = ES_ACCEPTED;
  17.       es->pcb = newpcb;
  18.       es->p = NULL;
  19.      
  20.       //传递新分配的结构体数据给新的pcb
  21.       tcp_arg(newpcb, es);
  22.      
  23.       //为新的连接设置receive回调函数
  24.       tcp_recv(newpcb, tcp_echoserver_recv);
  25.      
  26.       //为新的连接设置error回调函数
  27.       tcp_err(newpcb, tcp_echoserver_error);
  28.      
  29.       //为新的连接设置poll回调函数
  30.       tcp_poll(newpcb, tcp_echoserver_poll, 1);
  31.      
  32.       ret_err = ERR_OK;
  33.     }
  34.     else
  35.     {
  36.       /* return memory error */
  37.       ret_err = ERR_MEM;
  38.     }
  39.     return ret_err;  
  40.   }
  41.   


 楼主| 598330983 发表于 2017-1-14 11:09 | 显示全部楼层
 接下来便是tcp_echoserver_recv()这个回调函数,因为该函数比较大,这里就不再全部罗列代码了。对于使用者来说,只需要知道相应的判定条件来代表什么意思就足够了,如:
  1.   static err_t tcp_echoserver_recv(void *arg, struct tcp_pcb *tpcb, struct pbuf *p, err_t err)
  2.   {
  3.     struct tcp_echoserver_struct *es;
  4.     err_t ret_err;
  5.   
  6.     LWIP_ASSERT("arg != NULL",arg != NULL);
  7.     
  8.     es = (struct tcp_echoserver_struct *)arg;
  9.   
  10.     if (p == NULL)
  11.     {
  12.      //如果接收到空的帧,则释放连接
  13.      ...
  14.     }   
  15.     else if(err != ERR_OK)
  16.     {
  17.      //接收到一个非空的帧,但可能某些原因出错,导致返回值不为ERR_OK,故在此释放缓存
  18.      ...
  19.     }
  20.     else if(es->state == ES_ACCEPTED)
  21.     {
  22.      //连接成功,在这里需要设置sent回调函数
  23.      ...
  24.     }
  25.     else if (es->state == ES_RECEIVED)
  26.     {
  27.      //从客户端收到数据
  28.      ...
  29.     }
  30.     else
  31.     {
  32.      //当连接关闭时,还收到了数据
  33.      ...
  34.   
  35.     }
  36.     
  37.     return ret_err;
  38.   }
  39.   


 楼主| 598330983 发表于 2017-1-14 11:10 | 显示全部楼层
STM32F207的代码部分就暂时说到这里,现在的问题是,如何测试这代码的正确性呢?这就必须用到ST提供的echotool.exe程序了。该程序位于stm32f2x7_eth_lwip的PC_Software文件夹中。该程序必须在命令行打开,其大致参数如下所示:
  
  
0_1309762874AF1I.gif
  如果我们的serverip地址为192.168.0.8,那么可以输入如下命令进行测试:
  echotool.exe 192.168.0.8 /p tcp /r 7 /n 15 /t 2 /d Testing LwIP TCP echo server
  
  如果网络联通的话,测试成功将如下如下的画面,如图:
  
0_1309762878a9k1.gif




mmuuss586 发表于 2017-1-14 12:08 | 显示全部楼层

不错,谢谢分享;
 楼主| 598330983 发表于 2017-1-14 12:10 | 显示全部楼层
我今天搞这个遇到点问题,找了个不错的资料弄懂了,分享来的。
wen05080109 发表于 2017-9-21 17:11 | 显示全部楼层
好像PING不成功。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

266

主题

5573

帖子

22

粉丝
快速回复 在线客服 返回列表 返回顶部