//=====================================================================
//TITLE:
// STM32F2xx的tcp_echoserver例程解说
//AUTHOR:
// norains
//DATE:
// Monday 04-July-2011
//Environment:
// Keil MDK 4.2
// STM32F207 核心版
//===================================================================== 最近拿到STM32F207的核心版,板载有网卡芯片,自然要拿过来捣鼓一番。而对于一个从未接触过网络的菜鸟来说,最好的入门方式就是揣测ST公司的例程,所以今天norains也不例外。那么我们就一起来看看这个官方的例程吧!
ST关于TCP的例程分为client和server,根据字面意思,可以知道tcp_echoserver例程是将STM32F2xx作为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;
- }
复制代码 STM32F207的代码部分就暂时说到这里,现在的问题是,如何 测试这代码的正确性呢?这就必须用到ST提供的echotool.exe程序了。该程序位于stm32f2x7_eth_lwip的PC_Software文件夹中。该程序必须在命令行打开,其大致参数如下所示:
如果我们的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
如果网络联通的话,测试成功将如下如下的画面,如图:
|