0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

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

jf_pJlTbmA9 ? 來源:靈動MM32MCU ? 作者:靈動MM32MCU ? 2023-09-27 15:44 ? 次閱讀

前面介紹了基于Socket方式的以太網(wǎng)通訊,接下來給大家介紹基于TCP包的通訊。內(nèi)容分為基于MM32F3270以太網(wǎng)Client的使用與基于MM32F3270以太網(wǎng)Server的使用。

首先,對TCP有個簡單的介紹:

TCP是一種面向連接的、可靠的、基于字節(jié)流的傳輸層通信協(xié)議。即客戶端和服務(wù)器之間在交換數(shù)據(jù)之前會先建立一個TCP連接,才能相互傳輸數(shù)據(jù)。并且提供超時重發(fā),丟棄重復(fù)數(shù)據(jù),檢驗數(shù)據(jù),流量控制等功能,保證數(shù)據(jù)能從一端傳到另一端。

TCP優(yōu)點:可靠、穩(wěn)定,TCP的可靠體現(xiàn)在TCP在傳遞數(shù)據(jù)之前,會有三次握手來建立連接,而且在數(shù)據(jù)傳遞時,有確認、窗口、重傳、擁塞控制機制,在數(shù)據(jù)傳完后,還會斷開連接用來節(jié)約系統(tǒng)資源。

TCP的缺點:慢,效率低,占用系統(tǒng)資源高,易被攻擊,TCP在傳遞數(shù)據(jù)之前,要先建連接,這會消耗時間,而且在數(shù)據(jù)傳遞時,確認機制、重傳機制、擁塞控制機制等都會消耗大量的時間,而且要在每臺設(shè)備上維護所有的傳輸連接,事實上,每個連接都會占用系統(tǒng)的CPU、內(nèi)存等硬件資源。由于TCP存在確認機制和三次握手機制,這些是導(dǎo)致TCP容易被人利用,實現(xiàn)DOS、DDOS、CC等攻擊。

接下來,介紹Client 的使用實現(xiàn):

Demo使用MB-039開發(fā)板,在工程中使用LwIP+FreeRTOS,實驗展示如何制作一個Client端,并發(fā)送數(shù)據(jù),實驗使用到的硬件如下:

poYBAGIB1SyAHYynAAG39uXw7q0489.png

如圖是MB-039(完整原理圖可以通過MM32官網(wǎng)下載)的ETH部分。

各個信號引腳對應(yīng)如下:

pYYBAGIB1S6AEqaVAAAOapdym_Y980.png
poYBAGIB1TGAFwREAAi12qR49zc411.png

在進行Client實驗前,我們先了解需要使用到的API

1)netconn_new ()

2)netconn_connect ()

3)netconn_write ()

每一個函數(shù)實現(xiàn)的功能:

01、netconn_new ()

netconn_new的功能為創(chuàng)建一個新的連接結(jié)構(gòu),結(jié)構(gòu)類型可以為TCP/UDP其源碼如下:

struct netconn*
netconn_new_with_proto_and_callback(enum netconn_type t, u8_t proto, netconn_callback callback)
{
    struct netconn* conn;
    API_MSG_VAR_DECLARE(msg);
    API_MSG_VAR_ALLOC_RETURN_NULL(msg);

    conn = netconn_alloc(t, callback);
    if (conn != NULL) {
        err_t err;

        API_MSG_VAR_REF(msg).msg.n.proto = proto;
        API_MSG_VAR_REF(msg).conn = conn;
        err = netconn_apimsg(lwip_netconn_do_newconn,  API_MSG_VAR_REF(msg));
        if (err != ERR_OK) {
            LWIP_ASSERT("freeing conn without freeing pcb", conn->pcb.tcp == NULL);
            LWIP_ASSERT("conn has no recvmbox", sys_mbox_valid( conn->recvmbox));
#if LWIP_TCP
            LWIP_ASSERT("conn->acceptmbox shouldn't exist", !sys_mbox_valid( conn->acceptmbox));
#endif /* LWIP_TCP */
#if !LWIP_NETCONN_SEM_PER_THREAD
            LWIP_ASSERT("conn has no op_completed", sys_sem_valid( conn->op_completed));
            sys_sem_free( conn->op_completed);
#endif /* !LWIP_NETCONN_SEM_PER_THREAD */
            sys_mbox_free( conn->recvmbox);
            memp_free(MEMP_NETCONN, conn);
            API_MSG_VAR_FREE(msg);
            return NULL;
        }
    }
    API_MSG_VAR_FREE(msg);
    return conn;
}

從源碼中可以看出,其功能為申請并初始化一個netconn結(jié)構(gòu)體,同時在netconn_alloc函數(shù)中為conn變量創(chuàng)建一個接收郵箱(recvmbox),和一個信號量(conn->op_completed)。內(nèi)存申請成功后使用netconn_apimsg函數(shù)構(gòu)建一個消息,使用OS的系統(tǒng)郵箱發(fā)送給內(nèi)核,請求以太網(wǎng)協(xié)議棧去執(zhí)行l(wèi)wip_netconn_do_newconn()函數(shù),在執(zhí)行時使用conn->op_completed進行信號量同步,任務(wù)處理完成后,釋放一個信號量表示任務(wù)完成。

02、netconn_connect ()

netconn_connect作用為建立連接,在調(diào)用時將服務(wù)器端IP地址、端口號和本地的netconn結(jié)構(gòu)綁定,源碼如下:

err_t  netconn_connect(struct netconn* conn, const ip_addr_t* addr, u16_t port)
{
    API_MSG_VAR_DECLARE(msg);
    err_t err;

    LWIP_ERROR("netconn_connect: 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 */

    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_connect,  API_MSG_VAR_REF(msg));
    API_MSG_VAR_FREE(msg);

    return err;
}

從源碼中可以看出,其功能為使用netconn_apimsg創(chuàng)建一個消息,通過執(zhí)行l(wèi)wip_netconn_do_connect進行信號量的同步,將addr、port與conn進行綁定。

03、netconn_write ()

netconn_write()為處于穩(wěn)定狀態(tài)的TCP協(xié)議發(fā)送數(shù)據(jù)。TCP協(xié)議數(shù)據(jù)以數(shù)據(jù)流的方式傳遞,因此只需要知道地址、長度及需要發(fā)送的數(shù)據(jù)即可,其實際函數(shù)為netconn_write_vectors_partly(源碼較長,就不貼出來了)。重點關(guān)注一下官方API文檔對于apiflags參數(shù)的介紹:

* @param apiflags combination of following flags :
* - NETCONN_COPY: data will be copied into memory belonging to the stack
* - NETCONN_MORE: for TCP connection, PSH flag will be set on last segment sent
* - NETCONN_DONTBLOCK: only write the data if all data can be written at once

apiflags的值為NETCONN_COPY時,dataptr指針指向的數(shù)據(jù)將會被拷貝到為這些數(shù)據(jù)分配的內(nèi)部緩沖區(qū),在調(diào)用本函數(shù)之后可以直接對這些數(shù)據(jù)進行修改而不會影響數(shù)據(jù),但是拷貝的過程是需要消耗系統(tǒng)資源的,CPU需要參與數(shù)據(jù)的拷貝,而且還會占用新的內(nèi)存空間。

apiflags值為NETCONN_NOCOPY時,數(shù)據(jù)不會被拷貝而是直接使用dataptr指針來引用。但是這些數(shù)據(jù)在函數(shù)調(diào)用后不能立即被修改,因為這些數(shù)據(jù)可能會被放在當(dāng)前TCP連接的重傳隊列中,以防對方未收到數(shù)據(jù)進行重傳,而這段時間是不確定的。但是如果用戶需要發(fā)送的數(shù)據(jù)在ROM中(靜態(tài)數(shù)據(jù)),這樣子就無需拷貝數(shù)據(jù),直接引用數(shù)據(jù)即可。

apiflags值為NETCONN_MORE時,那么接收端在組裝這些TCP報文段的時候,會將報文段首部的PSH標志置一,這些數(shù)據(jù)完成組裝的時候,將會被立即遞交給上層應(yīng)用。

apiflags值為NETCONN_DONTBLOCK時,表示在內(nèi)核發(fā)送緩沖區(qū)滿的時候,再調(diào)用netconn_write()函數(shù)將不會被阻塞,而是會直接返回一個錯誤代碼ERR_VAL告訴應(yīng)用程序發(fā)送數(shù)據(jù)失敗,應(yīng)用程序可以自行處理這些數(shù)據(jù),在適當(dāng)?shù)臅r候進行重傳操作。

apiflags值為NETCONN_NOAUTORCVD時,表示在TCP協(xié)議接收到數(shù)據(jù)的時候,調(diào)用netconn_recv_data_tcp()函數(shù)的時候不會去更新接收窗口,只能由用戶自己調(diào)用netconn_tcp_recvd()函數(shù)完成接收窗口的更新操作。

了解了以上3個API,我們開始創(chuàng)建Client工程:

static void client(void* thread_param)
{
    struct netconn* conn;
    int ret;
    ip4_addr_t ipaddr;
    uint8_t send_buf[] = "This is MM32F3270 TCP Client Demon";         //(1)
    while(1) {
        conn = netconn_new(NETCONN_TCP);                       //(2)
        if (conn == NULL) {                                       // (3)
            printf("create conn failed!n");
            vTaskDelay(10);
            continue;
        }
        IP4_ADDR( ipaddr, DEST_IP_ADDR0, DEST_IP_ADDR1, DEST_IP_ADDR2, DEST_IP_ADDR3);                                           // (4)
        ret = netconn_connect(conn,  ipaddr, DEST_PORT);      // (5)
        if (ret == -1) {
            printf("Connect failed!n");
            netconn_close(conn);
            vTaskDelay(10);
            continue;
        }
        while (1) {
            ret = netconn_write(conn, send_buf, sizeof(send_buf), 0);  // (6)
            vTaskDelay(1000);
        }
    }

}

1)將需要發(fā)送的數(shù)據(jù)裝填進send_buf中

2)申請一個內(nèi)存區(qū)域,類型為TCP

3)如果conn為空表示申請內(nèi)存失敗

4)將地址賦值給ipaddr

5)創(chuàng)建連接,如果失敗則刪除conn

6)執(zhí)行數(shù)據(jù)發(fā)送

到這里已經(jīng)完成了工程的創(chuàng)建,但是還有一步比較重要的,配置我們的IP,將數(shù)據(jù)發(fā)送給服務(wù)器端,則需要知道服務(wù)器的地址。打開命令行窗口輸入:ipconfig

pYYBAGIB1TOARaWcAAEnlBhO5H8936.png

PC地址為:192.168.105.34,在sys_arch.h文件中對DEST_IP_ADDR0 、DEST_IP_ADDR1、DEST_IP_ADDR2、DEST_IP_ADDR3進行修改,DEST_PORT隨意修改,值得注意的同一個設(shè)備是如果創(chuàng)建多個網(wǎng)卡,PORT成不同的值即可,后面我們會進行這類實驗,設(shè)備IP需要設(shè)置在同一個網(wǎng)段內(nèi)通信才能進行IP_ADDR0、IP_ADDR1、IP_ADDR2,需要與PC地址保持一致,IP_ADDR3可以隨意設(shè)置(和PC地址不一致即可)。

#define DEST_IP_ADDR0               192
#define DEST_IP_ADDR1               168
#define DEST_IP_ADDR2               105
#define DEST_IP_ADDR3               34

#define DEST_PORT                  5001

#define IP_ADDR0                    192
#define IP_ADDR1                    168
#define IP_ADDR2                    105
#define IP_ADDR3                    137

將程序下載入開發(fā)板中,使用SSCOM工具進行如下設(shè)置:

poYBAGIB136AUNEzAAF-Q-Sbt_k799.png

點擊偵聽:

poYBAGIB14CAOSBcAAKTfLZKCLA036.png

可以正常偵聽并接收到數(shù)據(jù),表明實驗成功。實驗程序請登錄我們的官網(wǎng)下載MM32F3270 SDK,工程路徑如下:

~MM32F3270_Lib_Samples_V0.90Demo_appEthernet_DemoETH_RTOSFreertos_Client

來源:靈動MM32MCU


審核編輯:湯梓紅

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • 以太網(wǎng)
    +關(guān)注

    關(guān)注

    40

    文章

    5426

    瀏覽量

    171740
  • Socket
    +關(guān)注

    關(guān)注

    0

    文章

    212

    瀏覽量

    34696
  • TCP
    TCP
    +關(guān)注

    關(guān)注

    8

    文章

    1353

    瀏覽量

    79078
  • FreeRTOS
    +關(guān)注

    關(guān)注

    12

    文章

    484

    瀏覽量

    62182
收藏 人收藏

    評論

    相關(guān)推薦

    靈動微課堂 (第182講) | 基于MM32F3270 以太網(wǎng) Client_Socket使用

    :~\MM32F3270_Lib_Samples_V0.90\Demo_app\Ethernet_Demo\ETH_RTOS\Freertos_Client_socket下章的題目為《基于MM32F3270
    發(fā)表于 10-18 11:02

    靈動微課堂 (第184講) | 基于MM32F3270 以太網(wǎng) UDP使用

    _Lib_Samples_V0.90\Demo_app\Ethernet_Demo\ETH_RTOS\Freertos_UDP我們下節(jié)的題目為《基于MM32F3270以太網(wǎng)Client的使用》。
    發(fā)表于 10-18 11:13

    靈動微課堂 (第185講) | 基于MM32F3270 以太網(wǎng) Client使用

    前面介紹了基于Socket方式的以太網(wǎng)通訊,接下來給大家介紹基于TCP包的通訊。內(nèi)容分為基于MM32F3270以太網(wǎng)Client的使用與基于MM32
    發(fā)表于 10-18 11:21

    MM32F3270系列32位MCU的特點有哪些

    上海靈動微電子推出全新主流型MM32F3270系列32位MCU,此款MM32F3270系列是基于M3內(nèi)核的32位微控制器,MM32F3270適用于要求高集成度的高性能控制領(lǐng)域,如:工業(yè)控制、消防監(jiān)控
    發(fā)表于 11-03 07:20

    靈動微電子MM32F3270系列MCU的特點介紹

    上海靈動微電子推出全新主流型MM32F3270系列32位MCU,此款MM32F3270系列是基于M3內(nèi)核的32位微控制器,MM32F3270適用于要求高集成度的高性能控制領(lǐng)域,如:工業(yè)控制、消防監(jiān)控
    發(fā)表于 03-22 16:57 ?2163次閱讀

    【國產(chǎn)MCU移植】MM32F3270 EVBoard

    【國產(chǎn)MCU移植】MM32F3270 EVBoard
    發(fā)表于 12-03 17:21 ?5次下載
    【國產(chǎn)MCU移植】<b class='flag-5'>MM32F3270</b> EVBoard

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

    接下來給大家介紹基于TCP包的通訊。內(nèi)容分為基于MM32F3270以太網(wǎng)Client的使用與基于MM32F3270以太網(wǎng)Server的使用。
    發(fā)表于 02-08 15:10 ?0次下載
    基于<b class='flag-5'>MM32F3270</b> <b class='flag-5'>以太網(wǎng)</b> <b class='flag-5'>Client</b>使用

    MM32F3270 ADC注入通道

    MM32F3270 ADC注入通道
    的頭像 發(fā)表于 09-27 15:59 ?1002次閱讀
    <b class='flag-5'>MM32F3270</b> ADC注入通道

    使用MM32F3270 FSMC驅(qū)動OLED

    使用MM32F3270 FSMC驅(qū)動OLED
    的頭像 發(fā)表于 09-27 15:30 ?954次閱讀
    使用<b class='flag-5'>MM32F3270</b> FSMC驅(qū)動OLED

    使用MM32F3270 FSMC驅(qū)動TFT-LCD

    使用MM32F3270 FSMC驅(qū)動TFT-LCD
    的頭像 發(fā)表于 09-27 15:34 ?1046次閱讀
    使用<b class='flag-5'>MM32F3270</b> FSMC驅(qū)動TFT-LCD

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

    基于MM32F3270以太網(wǎng)HTTP使用
    的頭像 發(fā)表于 09-27 15:48 ?576次閱讀
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太網(wǎng)</b>HTTP使用

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

    基于MM32F3270以太網(wǎng)Server使用
    的頭像 發(fā)表于 09-27 15:46 ?503次閱讀
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太網(wǎng)</b>Server使用

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

    基于MM32F3270以太網(wǎng) UDP使用
    的頭像 發(fā)表于 09-27 15:42 ?503次閱讀
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太網(wǎng)</b>UDP使用

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

    基于MM32F3270以太網(wǎng)Server_Socket使用
    的頭像 發(fā)表于 09-27 15:41 ?474次閱讀
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太網(wǎng)</b>Server_Socket使用

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

    基于MM32F3270以太網(wǎng)Client_Socket使用
    的頭像 發(fā)表于 09-27 15:37 ?543次閱讀
    基于<b class='flag-5'>MM32F3270</b><b class='flag-5'>以太網(wǎng)</b><b class='flag-5'>Client</b>_Socket使用