乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      lwip之udp

       立志德美 2019-07-17

      1、結(jié)構(gòu)體聲明

      udp報文結(jié)構(gòu)示意圖
      udp

      #define UDP_HLEN 8  //udp首部長度
      
      PACK_STRUCT_BEGIN
      struct udp_hdr {
        PACK_STRUCT_FIELD(u16_t src);
        PACK_STRUCT_FIELD(u16_t dest);  /* src/dest UDP ports */
        PACK_STRUCT_FIELD(u16_t len);
        PACK_STRUCT_FIELD(u16_t chksum);
      } PACK_STRUCT_STRUCT;
      PACK_STRUCT_END

      udp_pcb控制塊聲明

      #define IP_PCB    ip_addr_t local_ip;    ip_addr_t remote_ip;    u8_t so_options;         u8_t tos;                 u8_t ttl               
      struct udp_pcb {
      /* Common members of all PCB types */
        IP_PCB;
      
        struct udp_pcb *next;
      
        u8_t flags;
        u16_t local_port, remote_port;
      
        udp_recv_fn recv; //接收回調(diào)函數(shù)
        void *recv_arg;  //接收回調(diào)函數(shù)的參數(shù)
      };
      
      typedef void (*udp_recv_fn)(void *arg, struct udp_pcb *pcb, struct pbuf *p,
          ip_addr_t *addr, u16_t port); //回調(diào)函數(shù)的typedef定義
      
      struct udp_pcb *udp_pcbs; //udp控制塊鏈表頭

      2、UDP底層接口函數(shù)——udp_input

      void udp_input(struct pbuf *p, struct netif *inp)
      {
        struct udp_hdr *udphdr;
        struct udp_pcb *pcb, *prev;
        struct udp_pcb *uncon_pcb;
        struct ip_hdr *iphdr;
        u16_t src, dest;
        u8_t local_match;
        u8_t broadcast;
      
        iphdr = (struct ip_hdr *)p->payload;
      
        //檢查數(shù)據(jù)的合法性,并移動指針至udp的頭部
        if (p->tot_len < (IPH_HL(iphdr) * 4 + UDP_HLEN) || pbuf_header(p, -(s16_t)(IPH_HL(iphdr) * 4))) {
          pbuf_free(p);
          goto end;
        }
      
        udphdr = (struct udp_hdr *)p->payload;
      
       //檢查該IP是否為廣播地址
        broadcast = ip_addr_isbroadcast(&current_iphdr_dest, inp);
      
        src = ntohs(udphdr->src);   //源端口號
        dest = ntohs(udphdr->dest); //目地端口號
      
        {
          prev = NULL;
          local_match = 0;    //與本地連接IP和端口號是否相同標(biāo)志
          uncon_pcb = NULL;   //未連接控制塊
      
      //查找udp_pcb控制塊
          for (pcb = udp_pcbs; pcb != NULL; pcb = pcb->next) {
            local_match = 0;
      
              if (pcb->local_port == dest) {
              if (
                 (!broadcast && ip_addr_isany(&pcb->local_ip)) ||
                 ip_addr_cmp(&(pcb->local_ip), &current_iphdr_dest) ||
                  (broadcast &&  (ip_addr_isany(&pcb->local_ip) ||
                    ip_addr_netcmp(&pcb->local_ip, ip_current_dest_addr(), &inp->netmask)))) {
      
                local_match = 1;
                if ((uncon_pcb == NULL) && 
                    ((pcb->flags & UDP_FLAGS_CONNECTED) == 0)) {
                           uncon_pcb = pcb;
                }
              }
            }
      
            if ((local_match != 0) &&
                (pcb->remote_port == src) &&
                (ip_addr_isany(&pcb->remote_ip) ||
                 ip_addr_cmp(&(pcb->remote_ip), &current_iphdr_src))) {
      //連接狀態(tài)的pcb放置在pcb控制塊首部
              if (prev != NULL) {
                prev->next = pcb->next;
                pcb->next = udp_pcbs;
                udp_pcbs = pcb;
              } else {
                UDP_STATS_INC(udp.cachehit);
              }
              break;
            }
            prev = pcb;
          }
      
          if (pcb == NULL) {
            pcb = uncon_pcb;
          }
        }
      
      //對接收的udp報文偽首部校驗
        if (pcb != NULL || ip_addr_cmp(&inp->ip_addr, &current_iphdr_dest)) {
          {
            if (udphdr->chksum != 0) {
              if (inet_chksum_pseudo(p, ip_current_src_addr(), ip_current_dest_addr(),
                                     IP_PROTO_UDP, p->tot_len) != 0) {
                pbuf_free(p);
                goto end;
              }
            }
          }
          if(pbuf_header(p, -UDP_HLEN)) {
      
            pbuf_free(p);
            goto end;
          }
          if (pcb != NULL) {
      //調(diào)用pcb接收回調(diào)函數(shù)處理接收的數(shù)據(jù)包
            if (pcb->recv != NULL) {
              pcb->recv(pcb->recv_arg, pcb, p, ip_current_src_addr(), src);
            } else {
              pbuf_free(p);
              goto end;
            }
          } else {
            pbuf_free(p);
          }
        } else {
          pbuf_free(p);
        }
      end:
        PERF_STOP("udp_input");
      }

      3、應(yīng)用層接口函數(shù)

      (1)發(fā)送函數(shù)
      err_t udp_send(struct udp_pcb *pcb, struct pbuf *p)
      {
        return udp_sendto(pcb, p, &pcb->remote_ip, pcb->remote_port);
      }
      err_t udp_sendto(struct udp_pcb *pcb, struct pbuf *p,
        ip_addr_t *dst_ip, u16_t dst_port)
      {
        struct netif *netif;
      
        netif = ip_route(dst_ip);    //查找網(wǎng)絡(luò)接口
        if (netif == NULL) {
          return ERR_RTE;
        }
      
        return udp_sendto_if(pcb, p, dst_ip, dst_port, netif);
      }
      
      err_t udp_sendto_if(struct udp_pcb *pcb, struct pbuf *p,
        ip_addr_t *dst_ip, u16_t dst_port, struct netif *netif)
      {
      
        struct udp_hdr *udphdr;
        ip_addr_t *src_ip;
        err_t err;
        struct pbuf *q; /* q will be sent down the stack */
      
      
        if (pcb->local_port == 0) {
          err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
          if (err != ERR_OK) {
            return err;
          }
        }
      
      //判斷pbuf是否能夠容納UDP_HLEN的空間,若無則申請。
        if (pbuf_header(p, UDP_HLEN)) {
      
          //申請PBUF_RAM類型的RAM空間 大小為PBUF_LINK_HLEN + PBUF_IP_HLEN + UDP_HLEN
          q = pbuf_alloc(PBUF_IP, UDP_HLEN, PBUF_RAM); 
          /* new header pbuf could not be allocated? */
          if (q == NULL) {
            return ERR_MEM;
          }
          if (p->tot_len != 0) {
           //連接兩個pbuf q 和pbuf p
            pbuf_chain(q, p);
          }
      
        } else {
      
         //pbuf中已經(jīng)為udp頭部預(yù)留了空間
          q = p;
        }
      
      
        udphdr = (struct udp_hdr *)q->payload;
        udphdr->src = htons(pcb->local_port);
        udphdr->dest = htons(dst_port);
        /* in UDP, 0 checksum means 'no checksum' */
        udphdr->chksum = 0x0000; 
      
      
        if (ip_addr_isany(&pcb->local_ip)) {
          src_ip = &(netif->ip_addr);
        } else {
          if (!ip_addr_cmp(&(pcb->local_ip), &(netif->ip_addr))) {
      
            if (q != p) {
              pbuf_free(q);
              q = NULL;
            }
            return ERR_VAL;
          }
      
          src_ip = &(pcb->local_ip);
        }
      
      
        {    
          udphdr->len = htons(q->tot_len);
      
          /* calculate checksum */
      #if CHECKSUM_GEN_UDP
          if ((pcb->flags & UDP_FLAGS_NOCHKSUM) == 0) {
            u16_t udpchksum;
            {
              udpchksum = inet_chksum_pseudo(q, src_ip, dst_ip, IP_PROTO_UDP, q->tot_len);
            }
      
            /* chksum zero must become 0xffff, as zero means 'no checksum' */
            if (udpchksum == 0x0000) {
              udpchksum = 0xffff;
            }
            udphdr->chksum = udpchksum;
          }
      #endif /* CHECKSUM_GEN_UDP */
      
          //調(diào)用ip層發(fā)送函數(shù)發(fā)送
          err = ip_output_if(q, src_ip, dst_ip, pcb->ttl, pcb->tos, IP_PROTO_UDP, netif);
      
        }
      
      //新申請的pbuf q需釋放
        if (q != p) {
          pbuf_free(q);
          q = NULL;
        }
      
        return err;
      }
      (2)控制塊的相關(guān)操作函數(shù)

      新建控制塊,pcb->ttl = UDP_TTL;

      #define UDP_TTL                 255  
      
      struct udp_pcb *udp_new(void)
      {
        struct udp_pcb *pcb;
        pcb = (struct udp_pcb *)memp_malloc(MEMP_UDP_PCB);
      
        if (pcb != NULL) {
          memset(pcb, 0, sizeof(struct udp_pcb));
          pcb->ttl = UDP_TTL;     //生存周期
        }
        return pcb;
      }

      綁定某一個本地ip地址和端口號,即設(shè)置pcb->local_port,pcb->local_ip

      err_t udp_bind(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
      {
        struct udp_pcb *ipcb;
        u8_t rebind;
      
        rebind = 0;
      
        for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
      
          if (pcb == ipcb) {
            rebind = 1;
          }
      
          if ((ipcb->local_port == port) &&(ip_addr_isany(&(ipcb->local_ip)) ||
                 ip_addr_isany(ipaddr) || ip_addr_cmp(&(ipcb->local_ip), ipaddr))) {
              return ERR_USE;
            }
      
        ip_addr_set(&pcb->local_ip, ipaddr); //設(shè)置pcb控制塊中的本地ip
      
      
        if (port == 0) {
          port = udp_new_port();   //申請一個新的端口號
          if (port == 0) {
            return ERR_USE;
          }
        }
        pcb->local_port = port;  ////設(shè)置pcb控制塊中的本地端口號
      
      
        if (rebind == 0) {
          pcb->next = udp_pcbs;
          udp_pcbs = pcb;
        }
      
        return ERR_OK;
      }

      連接遠程主機ip號和端口號,設(shè)置pcb->remote_ip, pcb->remote_port

      err_t udp_connect(struct udp_pcb *pcb, ip_addr_t *ipaddr, u16_t port)
      {
        struct udp_pcb *ipcb;
      
        if (pcb->local_port == 0) {
          err_t err = udp_bind(pcb, &pcb->local_ip, pcb->local_port);
          if (err != ERR_OK) {
            return err;
          }
        }
      
        ip_addr_set(&pcb->remote_ip, ipaddr);
        pcb->remote_port = port;
        pcb->flags |= UDP_FLAGS_CONNECTED;
      
        for (ipcb = udp_pcbs; ipcb != NULL; ipcb = ipcb->next) {
          if (pcb == ipcb) {
            return ERR_OK;
          }
        }
      
        pcb->next = udp_pcbs;
        udp_pcbs = pcb;
      
        return ERR_OK;
      }

      釋放某一個pcb

      void udp_remove(struct udp_pcb *pcb)
      {
        struct udp_pcb *pcb2;
      
        if (udp_pcbs == pcb) {
          udp_pcbs = udp_pcbs->next;
      
        } else {
          for (pcb2 = udp_pcbs; pcb2 != NULL; pcb2 = pcb2->next) { 
            if (pcb2->next != NULL && pcb2->next == pcb) {
              pcb2->next = pcb->next;
            }
          }
        }
        memp_free(MEMP_UDP_PCB, pcb);
      }

      斷開某一個連接

      void udp_disconnect(struct udp_pcb *pcb)
      {
        ip_addr_set_any(&pcb->remote_ip);
        pcb->remote_port = 0;
        pcb->flags &= ~UDP_FLAGS_CONNECTED;
      }

      4、udp 應(yīng)用案列

      建立一個udp服務(wù)器,回顯接收到的數(shù)據(jù)。

      void udp_echoserver_init(void)
      {
         struct udp_pcb *upcb;
         err_t err;
         upcb = udp_new();
         if (upcb)
         {
            err = udp_bind(upcb, IP_ADDR_ANY, UDP_SERVER_PORT);
      
            if(err == ERR_OK)
            {
             //注冊回調(diào)函數(shù)
              udp_recv(upcb, udp_echoserver_receive_callback, NULL);
            }
            else
            {
              udp_remove(upcb);
              printf("can not bind pcb");
            }
         }
         else
         {
           printf("can not create pcb");
         } 
      }
      
      
      void udp_echoserver_receive_callback(void *arg, struct udp_pcb *upcb, struct pbuf *p, struct ip_addr *addr, u16_t port)
      {
      
      
        udp_connect(upcb, addr, UDP_CLIENT_PORT);
      
        udp_send(upcb, p);
      
        udp_disconnect(upcb);
      
        pbuf_free(p);
      
      }

        本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
        轉(zhuǎn)藏 分享 獻花(0

        0條評論

        發(fā)表

        請遵守用戶 評論公約

        類似文章 更多