STM32F2xx的tcp_echoserver例程解說(shuō)
掃描二維碼
隨時(shí)隨地手機(jī)看文章
//=====================================================================
//TITLE:
// STM32F2xx的tcp_echoserver例程解說(shuō)
//AUTHOR:
// norains
//DATE:
// Monday 04-July-2011
//Environment:
// Keil MDK 4.2
// STM32F207 核心版
//=====================================================================
最近拿到STM32F207的核心版,板載有網(wǎng)卡芯片,自然要拿過(guò)來(lái)?yè)v鼓一番。而對(duì)于一個(gè)從未接觸過(guò)網(wǎng)絡(luò)的菜鳥(niǎo)來(lái)說(shuō),最好的入門(mén)方式就是揣測(cè)ST公司的例程,所以今天norains也不例外。那么我們就一起來(lái)看看這個(gè)官方的例程吧!
首先我們來(lái)了解C/S網(wǎng)絡(luò)程序的工作流程,如圖:
這個(gè)圖并不是norains所繪制的,而是網(wǎng)上流傳的一個(gè)名為《TCP/IP Socket網(wǎng)絡(luò)編程》的PPT所截取的。這個(gè)流程各位一定要熟悉,因?yàn)榻酉聛?lái)所描述的例子流程,和該圖例非常吻合。
ST關(guān)于TCP的例程分為client和server,根據(jù)字面意思,可以知道tcp_echoserver例程是將STM32F2xx作為server來(lái)用。而例程的第一步呢,便是初始化,調(diào)用的是tcp_echoserver_init()函數(shù)。
在tcp_echoserver_init()函數(shù)里,主要做了這么幾件事情:
1. 創(chuàng)建一個(gè)新的TCP協(xié)議控制塊
2. 綁定地址和端口號(hào)(port)
3. 開(kāi)始監(jiān)聽(tīng)(listen)
4. 設(shè)置accept的回調(diào)函數(shù)
其完整代碼如下:
voidtcp_echoserver_init(void)
{
//創(chuàng)建一個(gè)新的TCP控制塊
tcp_echoserver_pcb=tcp_new();
if(tcp_echoserver_pcb!=NULL)
{
err_terr;
//綁定到端口7
err=tcp_bind(tcp_echoserver_pcb,IP_ADDR_ANY,7);
if(err==ERR_OK)
{
//開(kāi)始監(jiān)聽(tīng)
tcp_echoserver_pcb=tcp_listen(tcp_echoserver_pcb);
//設(shè)置tcp_echoserver_accept為accept的回調(diào)函數(shù)
tcp_accept(tcp_echoserver_pcb,tcp_echoserver_accept);
}
else
{
printf("Cannotbindpcbn");//norains2011-7-4comment
}
}
else
{
printf("Cannotcreatenewpcbn");//norains2011-7-4comment
}
}
當(dāng)客戶端開(kāi)始連接之后,那么被設(shè)置的tcp_echoserver_accept()回調(diào)函數(shù)就會(huì)被調(diào)用。該函數(shù)主要是創(chuàng)建一個(gè)新的數(shù)據(jù)結(jié)構(gòu),并且將該數(shù)據(jù)結(jié)構(gòu)傳遞給底層的TCP,最后分別是設(shè)置receive,error和poll這三個(gè)回調(diào)函數(shù)。
tcp_echoserver_accept()代碼如下所示:
staticerr_ttcp_echoserver_accept(void*arg,structtcp_pcb*newpcb,err_terr)
{
err_tret_err;
structtcp_echoserver_struct*es;
LWIP_UNUSED_ARG(arg);
LWIP_UNUSED_ARG(err);
///給新的連接設(shè)置優(yōu)先級(jí)
tcp_setprio(newpcb,TCP_PRIO_MIN);
//分配一個(gè)結(jié)構(gòu)體空間以保持TCP的連接
es=(structtcp_echoserver_struct*)mem_malloc(sizeof(structtcp_echoserver_struct));
if(es!=NULL)
{
es->state=ES_ACCEPTED;
es->pcb=newpcb;
es->p=NULL;
//傳遞新分配的結(jié)構(gòu)體數(shù)據(jù)給新的pcb
tcp_arg(newpcb,es);
//為新的連接設(shè)置receive回調(diào)函數(shù)
tcp_recv(newpcb,tcp_echoserver_recv);
//為新的連接設(shè)置error回調(diào)函數(shù)
tcp_err(newpcb,tcp_echoserver_error);
//為新的連接設(shè)置poll回調(diào)函數(shù)
tcp_poll(newpcb,tcp_echoserver_poll,1);
ret_err=ERR_OK;
}
else
{
/*returnmemoryerror*/
ret_err=ERR_MEM;
}
returnret_err;
}
接下來(lái)便是tcp_echoserver_recv()這個(gè)回調(diào)函數(shù),因?yàn)樵摵瘮?shù)比較大,這里就不再全部羅列代碼了。對(duì)于使用者來(lái)說(shuō),只需要知道相應(yīng)的判定條件來(lái)代表什么意思就足夠了,如:
staticerr_ttcp_echoserver_recv(void*arg,structtcp_pcb*tpcb,structpbuf*p,err_terr)
{
structtcp_echoserver_struct*es;
err_tret_err;
LWIP_ASSERT("arg!=NULL",arg!=NULL);
es=(structtcp_echoserver_struct*)arg;
if(p==NULL)
{
//如果接收到空的幀,則釋放連接
...
}
elseif(err!=ERR_OK)
{
//接收到一個(gè)非空的幀,但可能某些原因出錯(cuò),導(dǎo)致返回值不為ERR_OK,故在此釋放緩存
...
}
elseif(es->state==ES_ACCEPTED)
{
//連接成功,在這里需要設(shè)置sent回調(diào)函數(shù)
...
}
elseif(es->state==ES_RECEIVED)
{
//從客戶端收到數(shù)據(jù)
...
}
else
{
//當(dāng)連接關(guān)閉時(shí),還收到了數(shù)據(jù)
...
}
returnret_err;
}
STM32F207的代碼部分就暫時(shí)說(shuō)到這里,現(xiàn)在的問(wèn)題是,如何測(cè)試這代碼的正確性呢?這就必須用到ST提供的echotool.exe程序了。該程序位于stm32f2x7_eth_lwip的PC_Software文件夾中。該程序必須在命令行打開(kāi),其大致參數(shù)如下所示:
如果我們的serverip地址為192.168.0.8,那么可以輸入如下命令進(jìn)行測(cè)試:
echotool.exe 192.168.0.8 /p tcp /r 7 /n 15 /t 2 /d Testing LwIP TCP echo server
如果網(wǎng)絡(luò)聯(lián)通的話,測(cè)試成功將如下如下的畫(huà)面,如圖: