前面重點(diǎn)對(duì)Client的創(chuàng)建方式及使用方式進(jìn)行了介紹,本節(jié)通過(guò)Server實(shí)驗(yàn)對(duì)TCP通信過(guò)程進(jìn)行一次介紹。
在TCP/IP協(xié)議中,傳輸層及以下層的機(jī)制是由內(nèi)核提供的。應(yīng)用層由用戶提供,應(yīng)用層程序?qū)νㄐ艛?shù)據(jù)進(jìn)行解析處理,傳輸層及以下層處理通信的細(xì)節(jié)(將數(shù)據(jù)從一端傳入另外一端)。應(yīng)用層數(shù)據(jù)通過(guò)協(xié)議棧發(fā)送到網(wǎng)絡(luò)上時(shí),每層協(xié)議都要增加一個(gè)數(shù)據(jù)部首(header),進(jìn)行一次封裝。其中不同的協(xié)議層對(duì)數(shù)據(jù)包有不同的稱(chēng)謂,在傳輸層叫段(segment),在網(wǎng)絡(luò)層叫做數(shù)據(jù)報(bào)(datagram),在鏈路層稱(chēng)為幀(frame)。
在通信過(guò)程中,發(fā)送端執(zhí)行以下動(dòng)作:首先程序進(jìn)行編碼,確定通信的建立連接、發(fā)送數(shù)據(jù)的時(shí)間。接著建立TCP連接,TCP根據(jù)應(yīng)用指示負(fù)責(zé)建立連接、發(fā)送數(shù)據(jù)及斷開(kāi)連接。TCP首部包括源端口號(hào)和目標(biāo)端口號(hào)、序號(hào)和校驗(yàn)和,加完首部后數(shù)據(jù)包繼續(xù)往下傳遞到IP層,IP層加上IP首部包括地址等信息用于尋址操作,之后將數(shù)據(jù)繼續(xù)往下傳遞附加數(shù)據(jù)鏈路層首部。最后發(fā)送時(shí)的分組數(shù)據(jù)包會(huì)加上以太網(wǎng)包尾(用于循環(huán)冗余校驗(yàn))。
主機(jī)端:收到數(shù)據(jù)包后會(huì)在以太網(wǎng)數(shù)據(jù)包中找到MAC地址,判斷是否為自己的數(shù)據(jù)包,如果不是則丟棄。如果是傳遞給IP層處理,以此類(lèi)推,不斷往上傳遞到TCP層。在TCP層通過(guò)校驗(yàn)和判斷數(shù)據(jù)是否損壞,然后檢查是否按序號(hào)接收數(shù)據(jù),最后檢查端口號(hào)。處理完成這一切后數(shù)據(jù)包繼續(xù)往上層發(fā)送,即應(yīng)用層。如果出現(xiàn)主機(jī)空間已滿等情況,主機(jī)則會(huì)發(fā)送“處理異?!蓖ㄖl(fā)送端。
實(shí)驗(yàn)使用MB-039開(kāi)發(fā)板,在工程中使用LwIP+FreeRTOS,實(shí)驗(yàn)展示如何制作一個(gè)TCP Server,并收發(fā)數(shù)據(jù),實(shí)驗(yàn)使用到的硬件如下:
如圖是MB-039(完整原理圖可以通過(guò)MM32官網(wǎng)下載)的ETH部分。
各個(gè)信號(hào)引腳對(duì)應(yīng)如下:
在進(jìn)行Server實(shí)驗(yàn)前,我們先了解需要使用到的API:
1)netconn_bind ()
2)netconn_listen ()
3)netconn_accept ()
以下分API展開(kāi)介紹:
01、netconn_bind ()
從源碼中可以看出其主要功能:為conn(服務(wù)器端)綁定地址與端口號(hào)。
err_t netconn_bind(struct netconn* conn, const ip_addr_t* addr, u16_t port) { API_MSG_VAR_DECLARE(msg); err_t err; LWIP_ERROR("netconn_bind: invalid conn", (conn != NULL), return ERR_ARG;); #if LWIP_IPV4 /* Don't propagate NULL pointer (IP_ADDR_ANY alias) to subsequent functions */ if (addr == NULL) { addr = IP4_ADDR_ANY; } #endif /* LWIP_IPV4 */ #if LWIP_IPV4 LWIP_IPV6 if ((netconn_get_ipv6only(conn) == 0) ip_addr_cmp(addr, IP6_ADDR_ANY)) { addr = IP_ANY_TYPE; } #endif /* LWIP_IPV4 LWIP_IPV6 */ API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; API_MSG_VAR_REF(msg).msg.bc.ipaddr = API_MSG_VAR_REF(addr); API_MSG_VAR_REF(msg).msg.bc.port = port; err = netconn_apimsg(lwip_netconn_do_bind, API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); return err; }
02、netconn_listen ()
netconn_listen指向的函數(shù)是:netconn_listen_with_backlog,作用:使服務(wù)器進(jìn)入監(jiān)聽(tīng)狀態(tài),等待遠(yuǎn)端的連接請(qǐng)求。
err_t netconn_listen_with_backlog(struct netconn* conn, u8_t backlog) { #if LWIP_TCP API_MSG_VAR_DECLARE(msg); err_t err; /* This does no harm. If TCP_LISTEN_BACKLOG is off, backlog is unused. */ LWIP_UNUSED_ARG(backlog); LWIP_ERROR("netconn_listen: invalid conn", (conn != NULL), return ERR_ARG;); API_MSG_VAR_ALLOC(msg); API_MSG_VAR_REF(msg).conn = conn; #if TCP_LISTEN_BACKLOG API_MSG_VAR_REF(msg).msg.lb.backlog = backlog; #endif /* TCP_LISTEN_BACKLOG */ err = netconn_apimsg(lwip_netconn_do_listen, API_MSG_VAR_REF(msg)); API_MSG_VAR_FREE(msg); return err; #else /* LWIP_TCP */ LWIP_UNUSED_ARG(conn); LWIP_UNUSED_ARG(backlog); return ERR_ARG; #endif /* LWIP_TCP */ }
03、netconn_accept ()
netconn_accept(代碼較長(zhǎng),這里不進(jìn)行粘貼)用于TCP服務(wù)器中,等待著遠(yuǎn)端主機(jī)的連接請(qǐng)求,并且建立一個(gè)新的TCP連接,在調(diào)用這個(gè)函數(shù)之前需要通過(guò)調(diào)用 listen()函數(shù)讓服務(wù)器進(jìn)入監(jiān)聽(tīng)狀態(tài)。accept()函數(shù)的調(diào)用會(huì)阻塞應(yīng)用線程直至與遠(yuǎn)程主機(jī)建立TCP連接。參數(shù)addr是一個(gè)返回結(jié)果參數(shù),它的值由accept()函數(shù)設(shè)置,其實(shí)就是遠(yuǎn)程主機(jī)的地址與端口號(hào)等信息,當(dāng)新的連接已經(jīng)建立后,遠(yuǎn)端主機(jī)的信息將保存在連接句柄中,能夠標(biāo)識(shí)連接對(duì)象。
了解了以上3個(gè)API,我們開(kāi)始創(chuàng)建Server工程:
static void server(void* thread_param) { struct netconn* conn, *newconn; err_t err; LWIP_UNUSED_ARG(arg); #if LWIP_IPV6 conn = netconn_new(NETCONN_TCP_IPV6); netconn_bind(conn, IP6_ADDR_ANY, LOCAL_PORT); #else /* LWIP_IPV6 */ conn = netconn_new(NETCONN_TCP); //① netconn_bind(conn, IP_ADDR_ANY, LOCAL_PORT); //② #endif /* LWIP_IPV6 */ LWIP_ERROR("tcpecho: invalid conn", (conn != NULL), return;); printf("The local port number is%dnn", LOCAL_PORT); netconn_listen(conn); //③ while (1) { err = netconn_accept(conn, newconn); //④ if (err == ERR_OK) { struct netbuf* buf; void* data; u16_t len; while ((err = netconn_recv(newconn, buf)) == ERR_OK) { //⑤ do { netbuf_data(buf, data, len); err = netconn_write(newconn, data, len, NETCONN_COPY); //⑥ } while (netbuf_next(buf) >= 0); netbuf_delete(buf); //⑦ } netconn_close(newconn); //⑧ netconn_delete(newconn); //⑨ } } }
1、申請(qǐng)一個(gè)連接結(jié)構(gòu),指定參數(shù)是NETCONN_TCP,即TCP連接
2、綁定本地的IP地址與端口號(hào)
3、使TCP服務(wù)器進(jìn)入監(jiān)聽(tīng)狀態(tài)
4、處理客戶端的連接請(qǐng)求,當(dāng)只有當(dāng)有客戶端發(fā)送連接請(qǐng)求的時(shí)候才會(huì)處理,否則將進(jìn)入阻塞態(tài),而客戶端的信息保存在newconn連接結(jié)構(gòu)中
5、接收數(shù)據(jù),并裝填進(jìn)buf
6、對(duì)接收的數(shù)據(jù)進(jìn)行轉(zhuǎn)發(fā)(指定為不拷貝方式NETCONN_COPY)
7、釋放數(shù)據(jù)空間
8、主動(dòng)關(guān)閉客戶端的連接
9、釋放newconn空間
到這里已經(jīng)完成了工程的創(chuàng)建,看一下PC的IP地址,設(shè)備需要處于同一網(wǎng)段,以方便測(cè)試。
打開(kāi)命令行窗口輸入:ipconfig
PC的地址為:192.168.105.34,在sys_arch.h文件中對(duì)DEST_IP_ADDR0 、DEST_IP_ADDR1、DEST_IP_ADDR2、DEST_IP_ADDR3進(jìn)行修改,DEST_PORT 隨意修改。
#define LOCAL_PORT 2021 #define IP_ADDR0 192 #define IP_ADDR1 168 #define IP_ADDR2 105 #define IP_ADDR3 21
將程序下載入開(kāi)發(fā)板中,使用NetAssist進(jìn)行如下設(shè)置:
1)協(xié)議設(shè)置,此時(shí)設(shè)備為Server,則PC為Client
2)設(shè)置遠(yuǎn)程主機(jī)地址(即設(shè)備地址)
3)端口號(hào)
點(diǎn)擊連接,若提示連接失敗,則Ping一下開(kāi)發(fā)板地址,可以正常Ping通則檢查端口號(hào);如果無(wú)法Ping通則需要對(duì)工程進(jìn)行檢查。
任意輸入字符進(jìn)行發(fā)送。
通過(guò)上圖可以觀察到發(fā)送成功,并且設(shè)備返回?cái)?shù)據(jù)與發(fā)送數(shù)據(jù)一致,表明實(shí)驗(yàn)成功。實(shí)驗(yàn)程序請(qǐng)登錄我們的官網(wǎng)下載MM32F3270 SDK,工程路徑如下:~MM32F3270_Lib_Samples_V0.90Demo_appEthernet_DemoETH_RTOSFreertos_Server。
來(lái)源:靈動(dòng)MM32MCU
審核編輯:湯梓紅
-
以太網(wǎng)
+關(guān)注
關(guān)注
41文章
5635瀏覽量
175985 -
通信
+關(guān)注
關(guān)注
18文章
6206瀏覽量
137835 -
Server
+關(guān)注
關(guān)注
0文章
94瀏覽量
24708 -
TCP
+關(guān)注
關(guān)注
8文章
1402瀏覽量
81063
發(fā)布評(píng)論請(qǐng)先 登錄
靈動(dòng)微課堂 (第182講) | 基于MM32F3270 以太網(wǎng) Client_Socket使用
靈動(dòng)微課堂 (第185講) | 基于MM32F3270 以太網(wǎng) Client使用
靈動(dòng)微課堂 (第186講) | 基于MM32F3270 以太網(wǎng) Server使用
MM32F3270系列32位MCU的特點(diǎn)有哪些
靈動(dòng)微電子MM32F3270系列MCU的特點(diǎn)介紹
【國(guó)產(chǎn)MCU移植】MM32F3270 EVBoard

基于MM32F3270 以太網(wǎng) Server使用

基于MM32F3270 以太網(wǎng) Client使用

評(píng)論