日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 运维知识 > windows >内容正文

windows

LwIP应用开发笔记之二:LwIP无操作系统UDP服务器

發(fā)布時間:2024/7/23 windows 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LwIP应用开发笔记之二:LwIP无操作系统UDP服务器 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

前面我們已經(jīng)完成了LwIP協(xié)議?;谶壿嫷幕疽浦?#xff0c;在這一節(jié)我們將以RAW API來實現(xiàn)UDP服務(wù)器。

1UDP協(xié)議簡述

UDP協(xié)議全稱是用戶數(shù)據(jù)報協(xié)議,在網(wǎng)絡(luò)中它與TCP協(xié)議一樣用于處理數(shù)據(jù)包,是一種無連接的協(xié)議。在OSI模型中,處于傳輸層,是IP協(xié)議的上層協(xié)議。UDP有不提供數(shù)據(jù)包分組、組裝和不能對數(shù)據(jù)包進行排序的缺點,也就是說,當(dāng)報文發(fā)送之后,是無法得知其是否安全完整到達的。

UDP協(xié)議的主要作用是將網(wǎng)絡(luò)數(shù)據(jù)流量壓縮成數(shù)據(jù)包的形式。一個典型的數(shù)據(jù)包就是一個二進制數(shù)據(jù)的傳輸單位。每一個數(shù)據(jù)包的前8個字節(jié)用來包含報頭信息,剩余字節(jié)則用來包含具體的傳輸數(shù)據(jù)。

UDP報頭由4個域組成,其中每個域各占用2個字節(jié),具體如下:源端口號、目標(biāo)端口號、數(shù)據(jù)報長度、校驗值。其數(shù)據(jù)結(jié)構(gòu)如下:

UDP協(xié)議使用端口號為不同的應(yīng)用保留其各自的數(shù)據(jù)傳輸通道。UDP和TCP協(xié)議正是采用這一機制實現(xiàn)對同一時刻內(nèi)多項應(yīng)用同時發(fā)送和接收數(shù)據(jù)的支持。數(shù)據(jù)發(fā)送一方(可以是客戶端或服務(wù)器端)將UDP數(shù)據(jù)包通過源端口發(fā)送出去,而數(shù)據(jù)接收一方則通過目標(biāo)端口接收數(shù)據(jù)。有的網(wǎng)絡(luò)應(yīng)用只能使用預(yù)先為其預(yù)留或注冊的靜態(tài)端口;而另外一些網(wǎng)絡(luò)應(yīng)用則可以使用未被注冊的動態(tài)端口。因為UDP報頭使用兩個字節(jié)存放端口號,所以端口號的有效范圍是從0到65535。一般來說,大于49151的端口號都代表動態(tài)端口。

數(shù)據(jù)報的長度是指包括報頭和數(shù)據(jù)部分在內(nèi)的總字節(jié)數(shù)。因為報頭的長度是固定的,所以該域主要被用來計算可變長度的數(shù)據(jù)部分。數(shù)據(jù)報的最大長度根據(jù)操作環(huán)境的不同而各異。從理論上說,包含報頭在內(nèi)的數(shù)據(jù)報的最大長度為65535字節(jié)。不過,一些實際應(yīng)用往往會限制數(shù)據(jù)報的大小,有時會降低到8192字節(jié)。

UDP協(xié)議使用報頭中的校驗值來保證數(shù)據(jù)的安全。校驗值首先在數(shù)據(jù)發(fā)送方通過特殊的算法計算得出,在傳遞到接收方之后,還需要再重新計算。如果某個數(shù)據(jù)報在傳輸過程中被第三方篡改或者由于線路噪音等原因受到損壞,發(fā)送和接收方的校驗計算值將不會相符,由此UDP協(xié)議可以檢測是否出錯。

2、UDP服務(wù)器設(shè)計

前面我們簡要的介紹了UDP協(xié)議及其數(shù)據(jù)報,接下來我們將考慮怎么實現(xiàn)基于UDP協(xié)議的服務(wù)器。

首先,我們來看一看與UDP相關(guān)的API函數(shù),并對它們作一個初步的介紹,應(yīng)為我們需要使用它們來實現(xiàn)我們的應(yīng)用。函數(shù)及說明如下:

了解了這些函數(shù),我們現(xiàn)在考慮其實現(xiàn)過程。對于UDP服務(wù)器端來說,實現(xiàn)相對簡潔。其實現(xiàn)步驟如下:

首先,生成一個新的UDP控制塊。

接著,綁定UDP控制塊到任意IP地址及制定端口。

最后,為UDP控制塊注冊數(shù)據(jù)處理回調(diào)函數(shù),這里需要說明一下,這就是RAW AIP的回調(diào)函數(shù)。根據(jù)你要實現(xiàn)的功能不同復(fù)雜程度完全不一樣。我們由于要實現(xiàn)一個回環(huán)服務(wù)器,所以相對簡單。只需要將收到的信息,以我們想要的方式發(fā)送回客戶端就可以了。

為了很好的實現(xiàn)UDP服務(wù)器,還有一個問題需要設(shè)計好,就是我們前面我們曾提到的端口。我們都知道TCP/IP協(xié)議族包括有很多的協(xié)議,那通訊究竟是針對哪一個協(xié)議發(fā)生的呢?所謂兩臺機器間的通訊,實際上是主機上的應(yīng)用進程間的通訊,端口號就是為了最終實現(xiàn)主機上應(yīng)用進程的通訊。我們常見且會在后續(xù)使用到的協(xié)議端口如下:

為了使用方便我們將這些端口定義為宏,并存儲到一個專門的文件中。在這里我們本次實現(xiàn)UDP服務(wù)器也需要制定一個端口,其實支持UDP的端口都沒問題,但為了方便描述我們制定其為回環(huán)顯示端口。

3UDP服務(wù)器實現(xiàn)

我們了解了其實現(xiàn)的基本過程,其實并不復(fù)雜。事實上,回調(diào)函數(shù)的內(nèi)容才是我們真正需要考慮的東西。我們將其實現(xiàn)分為兩個部分:一是UDP服務(wù)器的初始化部分;二是UDP服務(wù)器功能部分,也就是回調(diào)函數(shù)所執(zhí)行的內(nèi)容。

首先實現(xiàn)UDP服務(wù)器的初始化部分。初始化部分定義一個新的UDP控制塊,并將其綁定到任意IP地址及指定端口。然后注冊數(shù)據(jù)處理回調(diào)函數(shù)。

/* UDP初始化配置 */ void UDP_Server_Initialization(void) {static char * recv_arg="We recieved a UDP data\n";struct udp_pcb *upcb;/* 生成一個新的UDP控制塊 */upcb = udp_new();/* 綁定upcb塊到任意IP地址及指定端口*/udp_bind(upcb, IP_ADDR_ANY, UDP_ECHO_SERVER_PORT);/* 為upcb指定數(shù)據(jù)處理回調(diào)函數(shù) */udp_recv(upcb,UDPServerCallback,(void *)recv_arg); }

關(guān)于為什么要將本地IP綁定到任意IP呢?這是因為UDP服務(wù)器收到數(shù)據(jù)包后,LwIP會先判斷其數(shù)據(jù)包的目的IP和端口是否和本地注冊的PCB控制塊綁定的本地的IP和本地端口號是否匹配。所以我們綁定PCB控制塊本地IP設(shè)為IP_ADDR_ANY時,只要收到的數(shù)據(jù)包的目的IP非廣播地址,端口號匹配,那么均認為數(shù)據(jù)包的目的IP和端口是與本地注冊的PCB控制塊綁定的本地IP和端口號相匹配的。省去了自己構(gòu)造本地IP的過程。

初始化完畢后,注冊了數(shù)據(jù)處理回調(diào)函數(shù)。接下來需要實現(xiàn)回調(diào)函數(shù)的內(nèi)容。回調(diào)函數(shù)主要實現(xiàn)對數(shù)據(jù)的處理,這取決于自己的需求。在這里我們在接收到UDP客戶端數(shù)據(jù)包后,不對其作什么處理,因為這一數(shù)據(jù)本來無意義,我們對任何的客戶端請求給予固定的回復(fù)。

/* 定義UDP服務(wù)器數(shù)據(jù)處理回調(diào)函數(shù) */ static void UDPServerCallback(void *arg,struct udp_pcb *upcb,struct pbuf *revBuf,const ip_addr_t *addr,u16_t port) {struct pbuf *sendBuf = NULL;const char* reply = "This is reply!\n";pbuf_free(revBuf);sendBuf = pbuf_alloc(PBUF_TRANSPORT, strlen(reply)+1, PBUF_RAM);if(!sendBuf){return;}memset(sendBuf->payload,0,sendBuf->len);memcpy(sendBuf->payload, reply, strlen(reply));udp_sendto(upcb, sendBuf, addr, port);pbuf_free(sendBuf); }

對于這個回調(diào)函數(shù),它實際是賦給一個函數(shù)指針,所以雖然它的內(nèi)容和名稱可以隨意,但其格式是有要求的:void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,const ip_addr_t *addr, u16_t port)

4、結(jié)論

至此,我們完成了簡單的UDP服務(wù)器,在這里我們使用客戶端來測試一下這個UDP服務(wù)器,測試結(jié)果如下:

這里只測試了一個客戶端兩屆服務(wù)器的情況,其實連接多個客戶端的情況也是沒問題的。如下:

佷顯然,如果我們希望實現(xiàn)更復(fù)雜的UDP服務(wù)器,我們只需要將我們想實現(xiàn)的功能做到回調(diào)函數(shù)中就可以了。

歡迎關(guān)注:

創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎勵來咯,堅持創(chuàng)作打卡瓜分現(xiàn)金大獎

總結(jié)

以上是生活随笔為你收集整理的LwIP应用开发笔记之二:LwIP无操作系统UDP服务器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。