国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

LwIP RAW API TCP服務(wù)端客戶端編程及問題

這篇具有很好參考價(jià)值的文章主要介紹了LwIP RAW API TCP服務(wù)端客戶端編程及問題。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

TCP RAW API

1.1 新建TCP控制塊

函數(shù)原型:

struct tcp_pcb * tcp_new(void) 
1.2 綁定控制塊 tcp_bind()

用于服務(wù)端程序

將本地的 IP 地址、端口號與一個(gè)控制塊進(jìn)行綁定

函數(shù)原型:

err_t tcp_bind(struct tcp_pcb *pcb, const p_addr_t *ipaddr, u16_t port) 
1.3 設(shè)置控制塊處于監(jiān)聽狀態(tài) tcp_listen()

用于服務(wù)端程序,在接收連接前必須讓TCP處于監(jiān)聽狀態(tài)

#define          tcp_listen(pcb) tcp_listen_with_backlog(pcb, TCP_DEFAULT_LISTEN_BACKLOG)

struct tcp_pcb * tcp_listen_with_backlog_and_err(struct tcp_pcb *pcb, u8_t backlog, err_t *err) 
1.4 處理連接 tcp_accept()

用于服務(wù)端,處理客戶端連接

函數(shù)原型:

void tcp_accept(struct tcp_pcb *pcb, tcp_accept_fn accept) 

tcp_accept_fn回調(diào)函數(shù)類型定義:

 typedef err_t (*tcp_accept_fn)(void *arg, 
                                struct tcp_pcb *newpcb, 
                                err_t err); 
1.5 建立連接 tcp_connect()

TCP客戶端使用該函數(shù)主動發(fā)起連接

函數(shù)原型:

err_t tcp_connect(struct tcp_pcb *pcb, 
            const ip_addr_t *ipaddr, 
            u16_t port, 
            tcp_connected_fn connected) 

當(dāng)TCP連接成功connected回調(diào)函數(shù)就會被調(diào)用

tcp_connected_fn回調(diào)函數(shù)類型定義:

 typedef err_t (*tcp_connected_fn)(void *arg, 
                                    struct tcp_pcb *tpcb, 
                                   err_t err); 
1.6 終止連接 tcp_close()

客戶端應(yīng)用程序主動調(diào)用tcp_close()終止一個(gè)TCP連接

err_t tcp_close(struct tcp_pcb *pcb) 
1.7 接收數(shù)據(jù) tcp_recv()

函數(shù)原型:

void tcp_recv(struct tcp_pcb *pcb, tcp_recv_fn recv)   //注冊recv回調(diào)函數(shù)字段

回調(diào)函數(shù)原型:

typedef err_t (*tcp_recv_fn)(void *arg, 
                              struct tcp_pcb *tpcb, 
                              struct pbuf *p, 
                              err_t err);

該回調(diào)函數(shù)被調(diào)用的契機(jī):

  • 內(nèi)核接收到數(shù)據(jù),該函數(shù)被調(diào)用并將數(shù)據(jù)遞交給應(yīng)用層,也就是將數(shù)據(jù)傳入回調(diào)函數(shù)
  • 內(nèi)核檢測到對方主動終止TCP連接,也會觸發(fā)回調(diào)函數(shù)

所以數(shù)據(jù)的處理和應(yīng)用程序編寫就在該回調(diào)函數(shù)中實(shí)現(xiàn)

1.8 發(fā)送數(shù)據(jù) tcp_sent()
void tcp_sent(struct tcp_pcb *pcb, tcp_sent_fn sent) //將TCP控制塊sent回調(diào)函數(shù)字段注冊一個(gè)tcp_sent_fn的函數(shù),數(shù)據(jù)發(fā)送成功將調(diào)用sent回調(diào)函數(shù)通知應(yīng)用數(shù)據(jù)已經(jīng)被對方接收

tcp_sent_fn回調(diào)函數(shù)類型:

typedef err_t (*tcp_sent_fn)(void *arg, 
                              struct tcp_pcb *tpcb, 
                              u16_t len); 

服務(wù)端編程實(shí)現(xiàn)

1、服務(wù)器的初始化

struct ip4_addr_fmt {
    uint32_t addr1 : 8;
    uint32_t addr2 : 8;
    uint32_t addr3 : 8;
    uint32_t addr4 : 8;
};

void tcp_user_server_init(void)
{
    err_t err;

    tcp_server = tcp_new();  /* 創(chuàng)建TCP控制塊 */ 
    if (tcp_server == NULL)
    {
        LOG_LINE("failed to new tcp pcb");
        return;
    }

    err = tcp_bind(tcp_server, IP_ADDR_ANY, 9005);  /* 綁定IP端口 */ 
    if (err != ERR_OK)
    {
        LOG_LINE("failed to bind tcp");
        tcp_close(tcp_server);  
        return;
    }

    tcp_server = tcp_listen(tcp_server);    /* 啟用接聽 */ 

    tcp_accept(tcp_server, tcp_server_accept_cb); /* 設(shè)置收到客戶端連接請求的回調(diào)函數(shù) */
    LOG_LINE("TCP Server OK!!!");
    return;
}

接收請求連接的回調(diào):

err_t tcp_server_accept_cb(void *arg, struct tcp_pcb *newpcb, err_t err)
{
    struct ip4_addr_fmt *ip = (struct ip4_addr_fmt *)&newpcb->remote_ip;
    LOG_LINE("client %d.%d.%d.%d/%d connected", ip->addr1, ip->addr2, ip->addr3, ip->addr4, newpcb->remote_port);
    tcp_recv(newpcb, tcp_server_recv_cb);
    tcp_err(newpcb, tcp_err_cb);

    return ERR_OK;  /* 記得return ERR_OK,很重要/(ㄒoㄒ)/~~ */
}
  • tcp_recv(newpcb, tcp_server_recv_cb); 在接收請求回調(diào)中設(shè)置客戶端的數(shù)據(jù)接收函數(shù)回調(diào)函數(shù)
  • tcp_err(newpcb, tcp_err_cb);設(shè)置錯(cuò)誤的處理的回調(diào)函數(shù)

在測試過程中出現(xiàn)客戶端連接上后又?jǐn)嚅_,一直在反復(fù)重連,調(diào)試很久一段時(shí)間發(fā)現(xiàn)是因?yàn)?code>tcp_server_accept_cb函數(shù)的最后沒有return ERR_OK

客戶端數(shù)據(jù)的接收:

err_t tcp_server_recv_cb(void *arg, struct tcp_pcb *tpcb,
                             struct pbuf *p, err_t err)
{

    if (p != NULL)
    {
        struct pbuf *q;
        int recv_count = 0;

        tcp_recved(tpcb, p->tot_len);  /* 更新接收窗口 */
        for (q = p; q != NULL; q = q->next)
        {
            if (q->len > sizeof(recv_test_buf))
            {
                memcpy(recv_test_buf, q->payload, sizeof(recv_test_buf));
                break;
            }
            else 
            {
                if (recv_count >= sizeof(recv_test_buf))
                    break;
                memcpy(&recv_test_buf[recv_count], q->payload, q->len);
                recv_count += q->len;
            }
        }
        pbuf_free(p);
    }
    else if (err == ERR_OK) /* 接收成功但數(shù)據(jù)包是空的說明客戶端斷開連接 */
    {
        LOG_LINE("客戶端斷開連接");
        return tcp_close(tpcb);
    }

    struct ip4_addr_fmt *ip = (struct ip4_addr_fmt *)&tpcb->remote_ip;
    LOG_LINE("recv from %d.%d.%d.%d/%d, msg %s", 
                ip->addr1, ip->addr2, ip->addr3, ip->addr4, tpcb->remote_port, recv_test_buf);
    memset(recv_test_buf, 0, sizeof(recv_test_buf));

    return ERR_OK;  /* 記得return ERR_OK,很重要/(ㄒoㄒ)/~~ */
}
  • 接收數(shù)據(jù)前要調(diào)用tcp_recved(tpcb, p->tot_len); 更新接收窗口

客戶端編程實(shí)現(xiàn)

客戶端編程就比較簡單了

void tcp_user_client_init(void)
{
    tcp_client = tcp_new();
    if (tcp_client == NULL)
    {
        LOG_LINE("failed to new tcp client");
        return;
    }

    ip4_addr_t server_ip;
    IP4_ADDR(&server_ip, 192, 168, 57, 112);   /* 服務(wù)器IP地址 */

    err_t err;
    tcp_arg(tcp_client, tcp_client);
    tcp_err(tcp_client, tcp_client_err_cb);
    err = tcp_connect(tcp_client, &server_ip, 52000, tcp_client_connected_cb);
}

在成功連接的回調(diào)函數(shù)中設(shè)置客戶端數(shù)據(jù)接收回調(diào):

err_t tcp_client_connected_cb(void *arg, struct tcp_pcb *tpcb, err_t err)
{
    tcp_recv(tpcb, tcp_client_recv_cb); /* 設(shè)置數(shù)據(jù)接收回調(diào) */
    tcp_poll(tpcb, tcp_poll_cb, 10); /* 設(shè)置輪詢回調(diào) */
    LOG_LINE("連接服務(wù)器成功");
    return ERR_OK;       /* 記得return ERR_OK,很重要/(ㄒoㄒ)/~~ */
}

數(shù)據(jù)接收:

err_t tcp_client_recv_cb(void *arg, struct tcp_pcb *tpcb,
                             struct pbuf *p, err_t err)
{
    if (p != NULL)
    {
        struct pbuf *q;
        int recv_count = 0;

        tcp_recved(tpcb, p->tot_len);  /* 更新接收窗口 */
        for (q = p; q != NULL; q = q->next)
        {
            if (q->len > sizeof(recv_test_buf))
            {
                memcpy(recv_test_buf, q->payload, sizeof(recv_test_buf));
                break;
            }
            else 
            {
                if (recv_count >= sizeof(recv_test_buf))
                    break;
                memcpy(&recv_test_buf[recv_count], q->payload, q->len);
                recv_count += q->len;
            }
        }
        pbuf_free(p);
    }
    else if (err == ERR_OK) /* 接收成功但數(shù)據(jù)包是空的說明客戶端斷開連接 */
    {
        LOG_LINE("服務(wù)端斷開連接");
        tcp_close(tpcb);
        tcp_client = NULL;
        tcp_user_client_init();   /* 重連服務(wù)器 */
        return err;
    }

    struct ip4_addr_fmt *ip = (struct ip4_addr_fmt *)&tpcb->remote_ip;
   	LOG_LINE("recv from %d.%d.%d.%d/%d, msg %s", 
                ip->addr1, ip->addr2, ip->addr3, ip->addr4, tpcb->remote_port, recv_test_buf);
    memset(recv_test_buf, 0, sizeof(recv_test_buf));

    return ERR_OK;
}

在定時(shí)輪詢回調(diào)中向服務(wù)器發(fā)送數(shù)據(jù):

err_t tcp_poll_cb(void *arg, struct tcp_pcb *tpcb)
{
    static uint32_t test_count = 0;
    char buf[100] = { 0 };

    snprintf(buf, sizeof(buf), "tcp client test %d\r\n", test_count++);
    return tcp_write(tpcb, buf, sizeof(buf), 1); /* 記得return,很重要/(ㄒoㄒ)/~~ */
}

總結(jié)

在測試過程中出現(xiàn)客戶端連接上后又?jǐn)嚅_,一直在反復(fù)重連,調(diào)試很久一段時(shí)間發(fā)現(xiàn)是因?yàn)?code>tcp_server_accept_cb函數(shù)的最后沒有return ERR_OK 。
代碼還是要去寫,不想看著接口很簡單,想當(dāng)然一點(diǎn)問題也沒有,看一眼就會了,結(jié)果當(dāng)自己親自去寫的時(shí)候出現(xiàn)很多愚蠢的問題。文章來源地址http://www.zghlxwxcb.cn/news/detail-763807.html

到了這里,關(guān)于LwIP RAW API TCP服務(wù)端客戶端編程及問題的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【Linux | 網(wǎng)絡(luò)編程】TCP的服務(wù)端(守護(hù)進(jìn)程) + 客戶端

    【Linux | 網(wǎng)絡(luò)編程】TCP的服務(wù)端(守護(hù)進(jìn)程) + 客戶端

    上一節(jié),我們用了udp寫了一個(gè)服務(wù)端和客戶端之間通信的代碼,只要函數(shù)了解認(rèn)識到位,上手編寫是很容易的。 本章我們開始編寫tcp的服務(wù)端和客戶端之前通信的代碼,要認(rèn)識一批新的接口,并將我們之前學(xué)習(xí)的系統(tǒng)知識加進(jìn)來,做到融會貫通… 代碼詳情:?? Gitee 對于TC

    2024年01月16日
    瀏覽(24)
  • TCP IP網(wǎng)絡(luò)編程(四) 基于TCP的服務(wù)器端、客戶端

    TCP IP網(wǎng)絡(luò)編程(四) 基于TCP的服務(wù)器端、客戶端

    TCP/IP協(xié)議棧 ? TCP/IP協(xié)議棧 TCP/IP協(xié)議棧共分為4層,可以理解為數(shù)據(jù)收發(fā)分成了4個(gè)層次化過程。 ? TCP協(xié)議棧 ? UDP協(xié)議棧 鏈路層 鏈路層是物理連接領(lǐng)域標(biāo)準(zhǔn)化的結(jié)果,也是最基本的領(lǐng)域,專門定義LAN、WAN、MAN等網(wǎng)絡(luò)標(biāo)準(zhǔn)。兩臺主機(jī)通過網(wǎng)絡(luò)進(jìn)行數(shù)據(jù)交換,這需要像下圖所示

    2024年01月16日
    瀏覽(18)
  • Python網(wǎng)絡(luò)編程實(shí)戰(zhàn):構(gòu)建TCP服務(wù)器與客戶端

    Python網(wǎng)絡(luò)編程實(shí)戰(zhàn):構(gòu)建TCP服務(wù)器與客戶端 在信息化時(shí)代,網(wǎng)絡(luò)編程是軟件開發(fā)中不可或缺的一部分。Python作為一種功能強(qiáng)大的編程語言,提供了豐富的網(wǎng)絡(luò)編程庫和工具,使得開發(fā)者能夠輕松構(gòu)建各種網(wǎng)絡(luò)應(yīng)用。本文將詳細(xì)介紹如何在Python中進(jìn)行網(wǎng)絡(luò)編程,特別是如何使用

    2024年04月15日
    瀏覽(26)
  • C#實(shí)現(xiàn)簡單TCP服務(wù)器和客戶端網(wǎng)絡(luò)編程

    C#實(shí)現(xiàn)簡單TCP服務(wù)器和客戶端網(wǎng)絡(luò)編程

    在C#中進(jìn)行網(wǎng)絡(luò)編程涉及許多類和命名空間,用于創(chuàng)建和管理網(wǎng)絡(luò)連接、傳輸數(shù)據(jù)等。下面是一些主要涉及的類和命名空間: System.Net 命名空間: 這個(gè)命名空間提供了大部分網(wǎng)絡(luò)編程所需的類,包括: IPAddress :用于表示IP地址。 IPEndPoint :表示IP地址和端口號的組合。 Socke

    2024年02月11日
    瀏覽(37)
  • 《TCP/IP網(wǎng)絡(luò)編程》閱讀筆記--基于TCP的服務(wù)器端/客戶端

    《TCP/IP網(wǎng)絡(luò)編程》閱讀筆記--基于TCP的服務(wù)器端/客戶端

    目錄 1--TCP/IP協(xié)議棧 2--TCP服務(wù)器端默認(rèn)函數(shù)調(diào)用順序 3--TCP客戶端的默認(rèn)函數(shù)調(diào)用順序 4--Linux實(shí)現(xiàn)迭代回聲服務(wù)器端/客戶端 5--Windows實(shí)現(xiàn)迭代回聲服務(wù)器端/客戶端 6--TCP原理 7--Windows實(shí)現(xiàn)計(jì)算器服務(wù)器端/客戶端 ????????TCP/IP協(xié)議棧共分 4 層,可以理解為數(shù)據(jù)收發(fā)分成了 4 個(gè)層

    2024年02月10日
    瀏覽(30)
  • TCP IP網(wǎng)絡(luò)編程(五) 基于TCP的服務(wù)器端、客戶端 (補(bǔ)充)

    TCP IP網(wǎng)絡(luò)編程(五) 基于TCP的服務(wù)器端、客戶端 (補(bǔ)充)

    回聲客戶端出現(xiàn)的問題 在上一節(jié)基于TCP的服務(wù)器端、回聲客戶端中,存在問題: 如果數(shù)據(jù)太大,操作系統(tǒng)就有可能把數(shù)據(jù)分成多個(gè)數(shù)據(jù)包發(fā)送到客戶端,客戶端有可能在尚未收到全部數(shù)據(jù)包時(shí)就調(diào)用read函數(shù) 問題出在客戶端,而不是服務(wù)器端,先來對比一下客戶端與服務(wù)器端

    2024年02月09日
    瀏覽(37)
  • Socket網(wǎng)絡(luò)編程(TCP/IP)實(shí)現(xiàn)服務(wù)器/客戶端通信。

    Socket網(wǎng)絡(luò)編程(TCP/IP)實(shí)現(xiàn)服務(wù)器/客戶端通信。

    一.前言 回顧之前進(jìn)程間通信(無名管道,有名管道,消息隊(duì)列,共享內(nèi)存,信號,信號量),都是在同一主機(jī)由內(nèi)核來完成的通信。 那不同主機(jī)間該怎么通信呢? 可以使用Socket編程來實(shí)現(xiàn)。 Socket編程可以通過網(wǎng)絡(luò)來實(shí)現(xiàn)實(shí)現(xiàn)不同主機(jī)之間的通訊。 二.Socket編程的網(wǎng)絡(luò)模型如

    2024年02月08日
    瀏覽(37)
  • TCP流套接字編程(模擬多個(gè)客戶端與服務(wù)器交互)

    TCP流套接字編程(模擬多個(gè)客戶端與服務(wù)器交互)

    目錄 一、ServerSocket API 1.1、ServerSocket構(gòu)造方法 1.2、ServerSocket方法 二、Socket API? 2.1、socket構(gòu)造方法? 2.2、socket方法 三、TCP 中的長短連接 四、示例? 實(shí)現(xiàn)聊天室功能 五、存在的問題? ServerSocket 是創(chuàng)建TCP服務(wù)端Socket的API。 1.1、ServerSocket構(gòu)造方法 方法簽名 方法說明 ServerSocket

    2024年02月13日
    瀏覽(20)
  • python網(wǎng)絡(luò)編程:通過socket實(shí)現(xiàn)TCP客戶端和服務(wù)端

    python網(wǎng)絡(luò)編程:通過socket實(shí)現(xiàn)TCP客戶端和服務(wù)端

    目錄 寫在開頭 socket服務(wù)端(基礎(chǔ)) socket客戶端(基礎(chǔ)) 服務(wù)端實(shí)現(xiàn)(可連接多個(gè)客戶端)? 客戶端實(shí)現(xiàn) 數(shù)據(jù)收發(fā)效果 ? 近期可能會用python實(shí)現(xiàn)一些網(wǎng)絡(luò)安全工具,涉及到許多關(guān)于網(wǎng)絡(luò)的知識,逃不過的就是最基本的socket。本文將介紹如何通過python自帶的socket庫實(shí)現(xiàn)TCP客戶

    2024年03月21日
    瀏覽(27)
  • 【網(wǎng)絡(luò)編程】——基于TCP協(xié)議實(shí)現(xiàn)回顯服務(wù)器及客戶端

    【網(wǎng)絡(luò)編程】——基于TCP協(xié)議實(shí)現(xiàn)回顯服務(wù)器及客戶端

    個(gè)人主頁:兜里有顆棉花糖 歡迎 點(diǎn)贊?? 收藏? 留言? 加關(guān)注??本文由 兜里有顆棉花糖 原創(chuàng) 收錄于專欄【網(wǎng)絡(luò)編程】【Java系列】 本專欄旨在分享學(xué)習(xí)網(wǎng)絡(luò)編程的一點(diǎn)學(xué)習(xí)心得,歡迎大家在評論區(qū)交流討論?? TCP提供的API主要有兩個(gè)類 Socket ( 既會給服務(wù)器使用也會給客

    2024年02月03日
    瀏覽(44)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包