在线观看www成人影院-在线观看www日本免费网站-在线观看www视频-在线观看操-欧美18在线-欧美1级

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

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

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

有線網(wǎng)絡(luò)通信實(shí)驗(yàn)2之UDP協(xié)議

汽車電子技術(shù) ? 來源:滑小稽筆記 ? 作者:電子技術(shù)園地 ? 2023-03-01 14:29 ? 次閱讀

25.1 UDP協(xié)議概述

UDP協(xié)議是TCP/IP協(xié)議棧中傳輸層協(xié)議,是一個(gè)簡(jiǎn)單的面向數(shù)據(jù)報(bào)的協(xié)議,在傳輸層中還有一個(gè)TCP協(xié)議,UDP不提供數(shù)據(jù)包分組,組裝,無法對(duì)數(shù)據(jù)包進(jìn)行排序,當(dāng)報(bào)文發(fā)送出去之后無法知道是否安全,完整的到達(dá),但是由于UDP不屬于連接性協(xié)議,所以消耗資源小,處理速度快,通常用于音頻視頻和普通數(shù)據(jù)傳輸中,UDP數(shù)據(jù)包結(jié)構(gòu)如下圖所示。

圖片

端口號(hào)表示發(fā)送和接收進(jìn)程,UDP使用端口號(hào)為不同的應(yīng)用保留各自的數(shù)據(jù)傳輸通道,UDP和TCP都是采用端口號(hào)的形式對(duì)同一時(shí)刻多個(gè)應(yīng)用同時(shí)發(fā)送和接受數(shù)據(jù),而數(shù)據(jù)接收方則通過目標(biāo)端口接受數(shù)據(jù),有的網(wǎng)絡(luò)只能使用預(yù)先預(yù)留或注冊(cè)的靜態(tài)端口,而一些網(wǎng)絡(luò)可以使用沒有被注冊(cè)的動(dòng)態(tài)端口,由于UDP包頭使用兩個(gè)字節(jié)存放端口號(hào),所以端口的有效范圍0~65535,一般,大于49151的端口號(hào)都代表動(dòng)態(tài)端口。

數(shù)據(jù)包的長(zhǎng)度指的是包括包頭和數(shù)據(jù)部分在內(nèi)的總字節(jié)數(shù),由于包頭的長(zhǎng)度固定,所以這個(gè)區(qū)域主要用于計(jì)算可變長(zhǎng)度的數(shù)據(jù)部分,數(shù)據(jù)包的最大長(zhǎng)度根據(jù)操作環(huán)境選擇,理論上說,包括包頭在內(nèi)的數(shù)據(jù)報(bào)文最大長(zhǎng)度為65535字節(jié)。

UDP通過包頭中的校驗(yàn)和來保證數(shù)據(jù)的完整性,校驗(yàn)和首先在數(shù)據(jù)發(fā)送方通過特殊的算法計(jì)算出,傳遞到接收方之后,需要重新計(jì)算,如果某個(gè)數(shù)據(jù)在輸出過程中被篡改或某種原因損壞,那么發(fā)送方和接收方的校驗(yàn)和就會(huì)不一致,因此,UDP協(xié)議具有檢測(cè)報(bào)文是否出錯(cuò)的能力。

udp.c和udp.h這兩個(gè)文件就是負(fù)責(zé)實(shí)現(xiàn)UDP傳輸協(xié)議的文件,與UDP報(bào)文處理有關(guān)的函數(shù)之間的關(guān)系如下圖所示。

圖片

LWIP協(xié)議中API編程方式是基于回調(diào)機(jī)制的,在我們初始化應(yīng)用的時(shí)候必須為內(nèi)核中不同的事件注冊(cè)給出對(duì)應(yīng)的回調(diào)函數(shù),當(dāng)對(duì)應(yīng)的事件發(fā)生后這些回調(diào)函數(shù)就會(huì)被調(diào)用,udp.c中常用的API功能函數(shù)如下表所示。

API函數(shù) 函數(shù)功能
udp_new 新建一個(gè)UDP的PCB
udp_remove 將一個(gè)PCB控制塊從鏈表中刪除,并釋放這個(gè)控制塊的內(nèi)存
udp_bind 為UDP的PCN控制塊綁定一個(gè)本地IP地址和端口號(hào)
udp_connect 連接到指定IP地址主機(jī)的指定端口上
udp_disconnent 斷開連接,將控制塊設(shè)置為非連接狀態(tài)
udp_send 通過一個(gè)PCB控制塊發(fā)送數(shù)據(jù)
udp_recv 需要?jiǎng)?chuàng)建一個(gè)回調(diào)函數(shù),當(dāng)接受到數(shù)據(jù)的時(shí)候被調(diào)用

25.2 應(yīng)用編寫

在LWIP/app/udp_demo目錄下創(chuàng)建udp_demo.c和udp_demo.h文件。

25.2.1 udp_demo.c代碼編寫

#include "udp_demo.h" 
#include "delay.h"
#include "usart1.h"
#include "lcd.h"
#include "malloc.h"
#include "string.h"
#include "comm.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "lwip/tcp.h"
//UDP 測(cè)試全局狀態(tài)標(biāo)記變量
//bit6:數(shù)據(jù)接收狀態(tài)
//bit5:連接狀態(tài)
u8 udp_demo_flag;
//設(shè)置遠(yuǎn)端IP地址
void udp_demo_set_remoteip()
{
  u8 *tbuf ;
  LCD_Clear( WHITE ) ;
  POINT_COLOR = RED ;
  tbuf = mymalloc( SRAMIN, 100 ) ;                                  //申請(qǐng)內(nèi)存
  if( tbuf==NULL )
    return ;
  //前三個(gè)IP保持和DHCP得到的IP一致
  lwipdev.remoteip[ 0 ] = lwipdev.ip[ 0 ] ;
  lwipdev.remoteip[ 1 ] = lwipdev.ip[ 1 ] ;
  lwipdev.remoteip[ 2 ] = lwipdev.ip[ 2 ] ;
  lwipdev.remoteip[ 3 ] = 113 ;
  sprintf( ( char* )tbuf, "Remote IP:%d.%d.%d.", lwipdev.remoteip[0], lwipdev.remoteip[1], lwipdev.remoteip[2] ) ;
  LCD_ShowString( 30, 150, tbuf ) ;                //遠(yuǎn)端IP
  myfree( SRAMIN, tbuf ) ;
}
// UDP接收回調(diào)函數(shù)
u8 udp_demo_recvbuf[ UDP_DEMO_RX_BUFSIZE ] ;            //UDP接收數(shù)據(jù)緩沖區(qū)
void udp_demo_recv( void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port )
{
  u32 data_len=0 ;
  struct pbuf *q ;
  //接收到不為空的數(shù)據(jù)時(shí)
  if( p!=NULL )
  {
    memset( udp_demo_recvbuf, 0, UDP_DEMO_RX_BUFSIZE ) ;    //數(shù)據(jù)接收緩沖區(qū)清零
    //遍歷完整個(gè)pbuf鏈表
    for( q=p; q!=NULL; q=q->next )
    {
      //拷貝數(shù)據(jù)
      if( q->len>( UDP_DEMO_RX_BUFSIZE-data_len ) )
        memcpy( udp_demo_recvbuf+data_len, q->payload, UDP_DEMO_RX_BUFSIZE-data_len ) ;
      else
        memcpy( udp_demo_recvbuf+data_len, q->payload, q->len ) ;
      data_len += q->len ;
      //超出TCP客戶端接收數(shù)組,跳出
      if( data_len>UDP_DEMO_RX_BUFSIZE )
        break ;  
    }
    upcb->remote_ip = *addr ;                  //記錄遠(yuǎn)程主機(jī)的IP地址
    upcb->remote_port = port ;                //記錄遠(yuǎn)程主機(jī)的端口號(hào)
    lwipdev.remoteip[ 0 ] = upcb->remote_ip.addr&0xFF ;      //IADDR4
    lwipdev.remoteip[ 1 ] = ( upcb->remote_ip.addr>>8 )&0xFF ;  //IADDR3
    lwipdev.remoteip[ 2 ] = ( upcb->remote_ip.addr>>16 )&0xFF ;  //IADDR2
    lwipdev.remoteip[ 3 ] = ( upcb->remote_ip.addr>>24 )&0xFF ;  //IADDR1 
    udp_demo_flag |= 1<<6 ;                  //標(biāo)記接收到數(shù)據(jù)了
    pbuf_free( p ) ;                      //釋放內(nèi)存
  }
  else
  {
    udp_disconnect( upcb ) ;
    LCD_Clear( WHITE ) ;                    //清屏
    udp_demo_flag &= ~( 1<<5 ) ;                //標(biāo)記連接斷開
  }
}
// UDP服務(wù)器發(fā)送數(shù)據(jù)
const u8 *tcp_demo_sendbuf="STM32F103 UDP send data\\r\\n";
void udp_demo_senddata( struct udp_pcb *upcb )
{
  struct pbuf *ptr ;
  ptr = pbuf_alloc( PBUF_TRANSPORT, strlen( ( char* )tcp_demo_sendbuf ), PBUF_POOL ) ;//申請(qǐng)內(nèi)存
  if( ptr )
  {
    ptr->payload = ( void* )tcp_demo_sendbuf ;
    udp_send( upcb, ptr ) ;                    //udp發(fā)送數(shù)據(jù) 
    pbuf_free( ptr ) ;                                        //釋放內(nèi)存
  }
}
//關(guān)閉UDP連接
void udp_demo_connection_close( struct udp_pcb *upcb )
{
  udp_disconnect( upcb ) ;
  udp_remove( upcb ) ;                      //斷開UDP連接 
  udp_demo_flag &= ~( 1<<5 ) ;                  //標(biāo)記連接斷開
  LCD_Clear( WHITE ) ;                      //清屏
}
// UDP測(cè)試
void udp_demo_test()
{
   err_t err ;
  struct udp_pcb *udppcb ;                    //定義一個(gè)TCP服務(wù)器控制塊
  struct ip_addr rmtipaddr ;                                      //遠(yuǎn)端ip地址
  u8 *tbuf ;
  u8 res=0 ;
  udp_demo_set_remoteip() ;                    //先選擇IP
  LCD_Clear( WHITE ) ;                      //清屏
  tbuf = mymalloc( SRAMIN, 200 ) ;                //申請(qǐng)內(nèi)存
  //內(nèi)存申請(qǐng)失敗了,直接退出
  if( tbuf==NULL )
    return ;
  sprintf( ( char* )tbuf, "Local IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  LCD_ShowString( 30, 150, tbuf ) ;                //服務(wù)器IP
  sprintf( ( char* )tbuf, "Remote IP:%d.%d.%d.%d", lwipdev.remoteip[0], lwipdev.remoteip[1], lwipdev.remoteip[2], lwipdev.remoteip[3] ) ;
  LCD_ShowString( 30, 170, tbuf ) ;                //遠(yuǎn)端IP
  sprintf( ( char* )tbuf, "Remote Port:%d", UDP_DEMO_PORT ) ;
  LCD_ShowString( 30, 190, tbuf ) ;                //客戶端端口號(hào)
  LCD_ShowString( 30, 210, "STATUS:Disconnected" ) ;
  udppcb = udp_new() ;
  //創(chuàng)建成功
  if( udppcb )
  { 
    IP4_ADDR( &rmtipaddr, lwipdev.remoteip[0], lwipdev.remoteip[1], lwipdev.remoteip[2], lwipdev.remoteip[3] ) ;
    err = udp_connect( udppcb, &rmtipaddr, UDP_DEMO_PORT ) ;  //UDP客戶端連接到指定IP地址和端口
    if( err==ERR_OK )
    {
      err = udp_bind( udppcb, IP_ADDR_ANY, UDP_DEMO_PORT ) ; //綁定本地IP地址與端口號(hào)
      //綁定完成
      if( err==ERR_OK )
      {
        udp_recv( udppcb, udp_demo_recv, NULL ) ;      //注冊(cè)接收回調(diào)函數(shù)
        LCD_ShowString( 30, 210, "STATUS:Connected   " ) ;  //標(biāo)記連接上了
        udp_demo_flag |= 1<<5 ;              //標(biāo)記已經(jīng)連接上
        LCD_ShowString( 30, 230, "Receive Data:" ) ;      //提示消息
      }
      else
        res = 1 ;
    }
    else
      res = 1 ;
  }
  else
    res = 1 ;
  while( res==0 )
  {
    //是否收到數(shù)據(jù)
    if( udp_demo_flag&1<<6 )
    {
      LCD_ShowString( 30, 250, udp_demo_recvbuf ) ;      //顯示接收到的數(shù)據(jù)
      udp_demo_senddata( udppcb ) ;              //發(fā)送數(shù)據(jù)
      udp_demo_flag &= ~( 1<<6 ) ;              //標(biāo)記數(shù)據(jù)已經(jīng)被處理了
    } 
    lwip_periodic_handle() ;
    lwip_pkt_handle() ;
    delay_ms( 2 ) ;
  }
  udp_demo_connection_close( udppcb ) ;
  myfree( SRAMIN, tbuf ) ;
}

25.2.2 udp_demo.h代碼編寫

#ifndef _UDP_DEMO_H_
#define _UDP_DEMO_H_
#include "sys.h"
#define UDP_DEMO_RX_BUFSIZE  2000              //定義udp最大接收數(shù)據(jù)長(zhǎng)度 
#define UDP_DEMO_PORT      8089              //定義udp連接的端口 
void udp_demo_test( void ) ;                    //UDP測(cè)試
#endif

25.2.3 主函數(shù)代碼編寫

#include "sys.h"
#include "delay.h"
#include "usart1.h"
#include "tim.h"
#include "lcd.h"
#include "malloc.h"
#include "dm9000.h"
#include "lwip/netif.h"
#include "comm.h"
#include "lwipopts.h"
#include "udp_demo.h"
int main()
{
  u8 buf[ 30 ];
   STM32_Clock_Init( 9 ) ;                        //系統(tǒng)時(shí)鐘設(shè)置
  SysTick_Init( 72 ) ;                          //延時(shí)初始化
  USART1_Init( 72, 115200 ) ;                      //串口初始化為115200
  LCD_Init() ;                            //初始化LCD
  TIM3_Init( 1000, 719 ) ;                        //定時(shí)器3頻率為100hz
  my_mem_init( SRAMIN ) ;                      //初始化內(nèi)部?jī)?nèi)存池
  while( lwip_comm_init() ) ;                      //lwip初始化
  //等待DHCP獲取成功/超時(shí)溢出
  while( ( lwipdev.dhcpstatus!=2 )&&( lwipdev.dhcpstatus!=0xFF ) )
  {
    lwip_periodic_handle() ;                    //LWIP內(nèi)核需要定時(shí)處理的函數(shù)
    lwip_pkt_handle() ;
  }
  POINT_COLOR=RED;
  LCD_ShowString( 30, 110, "LWIP Init Successed" ) ;
  //打印動(dòng)態(tài)IP地址
  if( lwipdev.dhcpstatus==2 )
    sprintf( ( char* )buf, "DHCP IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  //打印靜態(tài)IP地址
  else
    sprintf( ( char* )buf, "Static IP:%d.%d.%d.%d", lwipdev.ip[0], lwipdev.ip[1], lwipdev.ip[2], lwipdev.ip[3] ) ;
  LCD_ShowString( 30, 130, buf ) ; 
  //得到網(wǎng)速
  if( ( DM9000_Get_SpeedAndDuplex()&0x02 )==0x02 )
    LCD_ShowString( 30, 150, "Ethernet Speed:10M" ) ;
  else
    LCD_ShowString( 30, 150, "Ethernet Speed:100M" ) ;
   while( 1 )
  {
    udp_demo_test();
    lwip_periodic_handle() ;
    lwip_pkt_handle() ;
    delay_ms( 2 ) ;
  }
}

25.3 實(shí)驗(yàn)結(jié)果

圖片

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

    關(guān)注

    9

    文章

    1928

    瀏覽量

    64717
  • UDP協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    69

    瀏覽量

    12718
  • 傳輸層協(xié)議
    +關(guān)注

    關(guān)注

    0

    文章

    6

    瀏覽量

    1284
收藏 人收藏

    評(píng)論

    相關(guān)推薦

    #硬聲創(chuàng)作季 #網(wǎng)絡(luò)通信 網(wǎng)絡(luò)通信原理-4.5 UDP協(xié)議解析1

    UDP協(xié)議網(wǎng)絡(luò)通信
    水管工
    發(fā)布于 :2022年11月30日 15:25:54

    #硬聲創(chuàng)作季 #網(wǎng)絡(luò)通信 網(wǎng)絡(luò)通信原理-4.5 UDP協(xié)議解析2

    UDP協(xié)議網(wǎng)絡(luò)通信
    水管工
    發(fā)布于 :2022年11月30日 15:26:13

    #硬聲創(chuàng)作季 #網(wǎng)絡(luò)通信 網(wǎng)絡(luò)通信原理-10.3 TCP與UDP協(xié)議03

    UDP協(xié)議網(wǎng)絡(luò)通信
    水管工
    發(fā)布于 :2022年11月30日 17:40:44

    #硬聲創(chuàng)作季 #網(wǎng)絡(luò)通信 網(wǎng)絡(luò)通信原理-10.4 TCP與UDP協(xié)議04-2

    UDP協(xié)議網(wǎng)絡(luò)通信
    水管工
    發(fā)布于 :2022年11月30日 17:41:26

    求labview和Linux網(wǎng)絡(luò)通信實(shí)

    求labview和Linux網(wǎng)絡(luò)通信實(shí)
    發(fā)表于 10-13 12:48

    請(qǐng)問誰有UDP協(xié)議網(wǎng)絡(luò)通信例程?

    UDP協(xié)議網(wǎng)絡(luò)通信例程基于enc28j60
    發(fā)表于 08-09 03:49

    為什么網(wǎng)絡(luò)通信實(shí)驗(yàn)用TCP客戶端模式時(shí)連接不上?

    戰(zhàn)艦V3上的實(shí)驗(yàn)50 網(wǎng)絡(luò)通信實(shí)驗(yàn),當(dāng)用TCP服務(wù)器模式時(shí),通信正常,用TCP客戶端模式時(shí)連接不上,為何?是否有更新的網(wǎng)絡(luò)通信實(shí)驗(yàn)代碼?請(qǐng)?zhí)峁?/div>
    發(fā)表于 08-16 04:35

    如何才能讓網(wǎng)絡(luò)通信實(shí)驗(yàn)支持10個(gè)UDP鏈接?

    大家好,我在使用探索者STM32F4開發(fā)板,寄存器例程,實(shí)驗(yàn)55 網(wǎng)絡(luò)通信實(shí)驗(yàn)。我修改了例程,想創(chuàng)建10個(gè)UDP端口監(jiān)聽,udppcb=udp_new()這里最多只能創(chuàng)建5個(gè),5個(gè)之后
    發(fā)表于 08-27 22:48

    為什么網(wǎng)絡(luò)通信實(shí)驗(yàn)網(wǎng)絡(luò)助手上接受到的先是456個(gè)字節(jié)?

    網(wǎng)絡(luò)通信實(shí)驗(yàn)里將ARMF407配置成sever,通過電腦上網(wǎng)絡(luò)助手接受ARM發(fā)送到數(shù)據(jù),將tcp_sever_sendbuf[1000]改成一個(gè)1000的大數(shù)組并賦值,但是在網(wǎng)絡(luò)助手上接受到的先是456個(gè)字節(jié)然后再是544個(gè)字
    發(fā)表于 09-02 02:54

    請(qǐng)問誰有F407網(wǎng)絡(luò)通信實(shí)驗(yàn)的視頻嗎?

    請(qǐng)問有沒有F407網(wǎng)絡(luò)通信實(shí)驗(yàn)的視頻啊,能方便給個(gè)鏈接或者地址嗎,謝謝了,急用嘞
    發(fā)表于 09-23 01:49

    如何把stm32f407網(wǎng)絡(luò)通信實(shí)驗(yàn)調(diào)通?

    最近在做網(wǎng)絡(luò)通信實(shí)驗(yàn),沒有調(diào)通,有沒有大神指點(diǎn)一下
    發(fā)表于 10-30 04:35

    請(qǐng)問探索者網(wǎng)絡(luò)通信實(shí)驗(yàn)的控制網(wǎng)頁該怎么寫呢?

    原子哥雖然有比較詳細(xì)的講解了網(wǎng)絡(luò)通信實(shí)驗(yàn),但是對(duì)于那個(gè)控制網(wǎng)頁怎么寫的卻沒有過多的涉及,請(qǐng)問有誰會(huì)寫這種控制網(wǎng)頁的,誠(chéng)心求教!
    發(fā)表于 11-06 04:35

    基于原子STM32F4的攝像頭與網(wǎng)絡(luò)通信實(shí)驗(yàn)

    網(wǎng)絡(luò)通信C/S方式將STM32攝像頭拍取的照片傳輸?shù)诫娔X端在PC端開發(fā)可視化界面接受攝像頭數(shù)據(jù)并更新顯示2.實(shí)施步驟:1.參考STM32原子攝像頭實(shí)驗(yàn)網(wǎng)絡(luò)通信實(shí)驗(yàn)例程,主要需要了解以
    發(fā)表于 08-03 06:04

    基于UDP協(xié)議網(wǎng)絡(luò)通信應(yīng)用程序

    基于UDP協(xié)議網(wǎng)絡(luò)通信應(yīng)用程序(UDP-Socket)前兩篇文章介紹了基于TCP/IP協(xié)議網(wǎng)絡(luò)通信
    發(fā)表于 11-05 08:29

    嵌入式Linux應(yīng)用程序開發(fā)-(9)UDP網(wǎng)絡(luò)通信應(yīng)用程序(UDP-Socket)

    基于UDP協(xié)議網(wǎng)絡(luò)通信應(yīng)用程序(UDP-Socket)前兩篇文章介紹了基于TCP/IP協(xié)議網(wǎng)絡(luò)通信
    發(fā)表于 11-02 12:21 ?35次下載
    嵌入式Linux應(yīng)用程序開發(fā)-(9)<b class='flag-5'>UDP</b><b class='flag-5'>網(wǎng)絡(luò)通信</b>應(yīng)用程序(<b class='flag-5'>UDP</b>-Socket)
    主站蜘蛛池模板: 女上男下边吃奶边做视频成都| 五月天婷婷影院| 爽好舒服老师快点| 欧美成人在线影院| xxxx欧美69免费| 欧美高清成人videosex| 五月婷婷影视| 天天搞一搞| 国产精品美女自在线观看免费| 日韩三级毛片| 夜色伊人| 末发育女一区二区三区| 欧美xingai| 国产69精品久久| 日日射天天射| 午夜影皖| 新天堂网| 伊人狼人综合| 丁香花五月天婷婷| 国产精品资源网| 黄色一级片毛片| 精品伊人久久香线蕉| 美女视频黄免费| 欧美色碰碰碰免费观看长视频| 色视频在线网站| 婷婷色站| 天天看影院| 午色| 日韩色爱| 国产二区三区| 日夜夜操| h国产在线观看| 68日本xxxxxxxxx18能看的| 性xxxx欧美| 亚洲啪啪| 高清一区二区三区| 国产成人精品一区| 色偷偷91久久综合噜噜噜噜| 深爱五月综合网| 日本一区二区三区四区不卡| 琪琪午夜免费影院在线观看|