rtthread,lwip,udp实现广播接收

我调通的代码:

#include <rtthread.h>
#include <string.h>

//#include <app_sfcon1_tcp.h>

//#if !defined(SAL_USING_POSIX)
//#error "Please enable SAL_USING_POSIX!"
//#else
//#include <sys/time.h>
//#include <sys/select.h>
//#endif
#include <sys/socket.h> /* 使用BSD socket,需要包含socket.h头文件 */
//#include "netdb.h"

#include <lwip/opt.h>
#include <lwip/sockets.h>
#include <lwip/inet_chksum.h>
#include <netif/etharp.h>
#include <netif/ethernetif.h>
#include <lwip/ip.h>
#include <lwip/init.h>

#include <lwip/init.h>


#include "lwip/udp.h"
#include "lwip/def.h"

#define DEBUG_UDP_SERVER

#define DBG_TAG               "UDP"
#ifdef DEBUG_UDP_SERVER
#define DBG_LVL               DBG_LOG
#else
#define DBG_LVL               DBG_INFO /* DBG_ERROR */
#endif
#include <rtdbg.h>

#define BUFSZ   1024

static int started = 0;
static int is_running = 0;
static int port = 11010;
#define UDP_DEMO_RX_BUFSIZE 1024
unsigned char udp_demo_recvbuf[UDP_DEMO_RX_BUFSIZE];
void udp_demo_recv(void *arg,struct udp_pcb *upcb,struct pbuf *p,struct ip_addr *addr,u16_t port)
{
  unsigned int data_len = 0;
  struct pbuf *q;
  u32_t addr1;
  if(p!=NULL)        //接收到不为空的数据时
  {
          rt_memset(udp_demo_recvbuf,0,UDP_DEMO_RX_BUFSIZE);  //数据接收缓冲区清零
          for(q=p;q!=NULL;q=q->next)//遍历完整个pbuf链表
          {
                  //判断要拷贝到UDP_DEMO_RX_BUFSIZE中的数据是否大于UDP_DEMO_RX_BUFSIZE的剩余空间,如果大于
                  //的话就只拷贝UDP_DEMO_RX_BUFSIZE中剩余长度的数据,否则的话就拷贝所有的数据
                  if(q->len > (UDP_DEMO_RX_BUFSIZE-data_len)) rt_memcpy((udp_demo_recvbuf+data_len),q->payload,(UDP_DEMO_RX_BUFSIZE-data_len));//拷贝数据
                  else rt_memcpy((udp_demo_recvbuf+data_len),q->payload,q->len);
                  data_len += q->len;         
                  if(data_len > UDP_DEMO_RX_BUFSIZE) break; //超出TCP客户端接收数组,跳出       
          }
          LOG_D("Received data = ");
          for(unsigned char i = 0;i<data_len;i++)
          {
             LOG_D("%x",udp_demo_recvbuf[i]);
          }
          LOG_D("\n");
          rt_memcpy(&addr1,addr,sizeof(addr1));
//          upcb->remote_ip=*addr;                                 //记录远程主机的IP地址
//          upcb->remote_port=port;                          //记录远程主机的端口号
//          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
         LOG_D("ip1 = %d", (addr1&0xff));                 //IADDR4
          LOG_D("ip2 = %d",(addr1>>8)&0xff); //IADDR3
          LOG_D("ip3 = %d",(addr1>>16)&0xff);//IADDR2
          LOG_D("ip4 = %d",(addr1>>24)&0xff);//IADDR1
          LOG_D("port = %d",port);//IADDR1
          //udp_demo_flag|=1<<6;        //标记接收到数据了
          pbuf_free(p);//释放内存
  }else
  {
          udp_disconnect(upcb);
//          udp_demo_flag &= ~(1<<5);        //标记连接断开
  }
}
static void udpserv_connector4_entry(void *paramemter)
{
    int sock;
    int bytes_read;
    char *recv_data;
    socklen_t addr_len;
    struct sockaddr_in server_addr, client_addr;

    struct timeval timeout;
    fd_set readset;
    

    /* 分配接收用的数据缓冲 */
    recv_data = rt_malloc(BUFSZ);
    if (recv_data == RT_NULL)
    {
        LOG_E("No memory");
        return;
    }

    
    /* 初始化服务端地址 */
    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(port);
    server_addr.sin_addr.s_addr = INADDR_ANY;//INADDR_NONE;//
    rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));

    /* 创建一个socket,类型是SOCK_DGRAM,UDP类型 */
//    if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
//    {
//        LOG_E("Create udp socket error");
//        goto __exit;
//    }

//    setsockopt(sock,SOL_SOCKET,SO_BROADCAST,( void *)&optval,sizeof(optval));
udp_recv
//    /* 绑定socket到服务端地址 */
//    if (bind(sock, (struct sockaddr *)&server_addr,
//             sizeof(struct sockaddr)) == -1)
   if (udp_bind(sock, IP_ADDR_BROADCAST,port) == -1)           
//    {
//        LOG_E("Unable to bind");
//        goto __exit;
//    }
      struct udp_pcb *udp_pcb;
      udp_pcb = udp_new();  
     if(udp_pcb!=NULL)
     {  
        ip_set_option(udp_pcb, SOF_BROADCAST);
        udp_bind(udp_pcb,IP_ADDR_ANY,11010);//组播端口  
        udp_recv(udp_pcb,udp_demo_recv,NULL);//接收回调函数  
     }  


    addr_len = sizeof(struct sockaddr);
    LOG_I("UDPServer Waiting for client on port %d...", port);

    started = 1;
    is_running = 1;

    timeout.tv_sec = 3;
    timeout.tv_usec = 0;

    while (is_running)
    {
      rt_thread_delay(100);
//        FD_ZERO(&readset);
//        FD_SET(sock, &readset);

        /* Wait for read or write */
//        if (select(sock + 1, &readset, RT_NULL, RT_NULL, &timeout) == 0)
//            continue;

        /* 从sock中收取最大BUFSZ - 1字节数据 */
//        bytes_read = recvfrom(sock, recv_data, BUFSZ - 1, 0,
//                              (struct sockaddr *)&client_addr, &addr_len);
       bytes_read = recv(sock, recv_data, BUFSZ - 1, 0);
       if (bytes_read < 0)
       {
           LOG_E("Received error, close the connect.");
           goto __exit;
       }
       else if (bytes_read == 0)
       {
           LOG_W("Received warning, recv function return 0.");
           continue;
       }
       else
       {
           recv_data[bytes_read] = '\0'; /* 把末端清零 */

           /* 输出接收的数据 */
           LOG_D("Received data = %s", recv_data);
//          sendto(sock, recv_data, rt_strlen(recv_data), 0,
//               (struct sockaddr *)&client_addr, sizeof(struct sockaddr));


           /* 如果接收数据是exit,退出 */
           if (strcmp(recv_data, "exit") == 0)
           {
               goto __exit;
           }
       }
    }

__exit:
    if (recv_data)
    {
        rt_free(recv_data);
        recv_data = RT_NULL;
    }
    if (sock >= 0)
    {
        closesocket(sock);
        sock = -1;
    }
    started = 0;
    is_running = 0;
}


//移植正点原子的UDP通信历程。
//1.将ENC28J60_Write(ERXFCON,ERXFCON_UCEN|ERXFCON_CRCEN|ERXFCON_PMEN);//能实现UDP,TCP的收发。但组播数据不行。
//   修改为ENC28J60_Write(ERXFCON,ERXFCON_CRCEN);//实现组播

//2.打开LWIP中的IGMP。在opt.h文件中    #define LWIP_IGMP                       1

//3.在ethernetif.c中的static err_t low_level_init(struct netif *netif)中,添加NETIF_FLAG_IGMP

//netif->flags = NETIF_FLAG_BROADCAST|NETIF_FLAG_ETHARP|NETIF_FLAG_LINK_UP|NETIF_FLAG_IGMP;//添加IGMP

//4.在lwip_comm.c中的void lwip_periodic_handle()中加入

//#if LWIP_IGMP
//        if(lwip_localtime-IGMPTimer >= IGMP_TMR_INTERVAL)
//        {
//                IGMPTimer = lwip_localtime;
//                    igmp_tmr();
//         }
//#endif

//周期性处理igmp_tmr();函数

//5.UDP初始化

//void Init_UDP_Server(void)
//{
//    IP4_ADDR(&ipgroup, 224,0,0,50);//组播IP地址  
//#if LWIP_IGMP  
//    igmp_joingroup(IP_ADDR_ANY,(struct ip_addr *)(&ipgroup));//组播加入当前  
//#endif  
//    udp_server_pcb = udp_new();  
//    if(udp_server_pcb!=NULL){  
//        udp_bind(udp_server_pcb,IP_ADDR_ANY,9999);//组播端口  
//        udp_recv(udp_server_pcb,udp_demo_recv,NULL);//接收回调函数  
//    }  
//}

//6.添加组播发送函数

void multicast_send_data(unsigned char * data,unsigned short len)  
{  
//    struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT,len, PBUF_RAM);  
//    memcpy(p->payload, data, len);
//        udp_sendto(udp_server_pcb, p,(struct ip_addr *) (&ipgroup),9999);  
//    pbuf_free(p);  
}

//7.UDP接受回调函数

//UDP回调函数

static void usage(void)
{
    rt_kprintf("Usage: udpserver -p <port>\n");
    rt_kprintf("       udpserver --stop\n");
    rt_kprintf("       udpserver --help\n");
    rt_kprintf("\n");
    rt_kprintf("Miscellaneous:\n");
    rt_kprintf("  -p           Specify the host port number\n");
    rt_kprintf("  --stop       Stop udpserver program\n");
    rt_kprintf("  --help       Print help information\n");
}

static void udpserver_sfcon4_config(int argc, char** argv)
{
    rt_thread_t tid;

    tid = rt_thread_create("udp_serv_sfcon4",
        udpserv_connector4_entry, RT_NULL,
        2048, RT_THREAD_PRIORITY_MAX/3, 20);
    if (tid != RT_NULL)
    {
        rt_thread_startup(tid);
    }
    return;

//__usage:
//    usage();
}
//INIT_APP_EXPORT(udpserver_sfcon4_config);
//#ifdef RT_USING_FINSH
MSH_CMD_EXPORT_ALIAS(udpserver_sfcon4_config, udpserver11,
    Start a udp server. Help: udpserver --help);
//#endif
 

 

参考:http://www.openedv.com/forum.php?mod=viewthread&tid=107160&page=1#pid593578

恩,我实现了,我用的是

g_pcb = udp_new();
udp_bind(g_pcb,IP_ADDR_BROADCAST,UDP_DEMO_PORT);
udp_recv(g_pcb,udp_server_recv,NULL);

void udp_server_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p,struct ip_addr *addr, u16_t port)
{
        struct ip_addr destAddr = *addr;
        destipaddr2 = *addr;
        if(p != NULL)
        {
                printf("\r\nIP:%d.%d.%d.%d",((uint32_t)(destAddr.addr)>>0&0xff),((uint32_t)(destAddr.addr)>>8)&0xff,((uint32_t)(destAddr.addr)>>16)&0xff,((uint32_t)(destAddr.addr)>>24)&0xff);
                printf("\r\nport:%d",port);       
                udp_flag = 1;
                udp_sendto(pcb,p,&destAddr,port);
                pbuf_free(p);                
        }
}


udp_flag 是标记收到广播数据,发送函数用的是原子哥的教程里的发送函数,这个子函数里的udp_sendto(pcb,p,&destAddr,port); 是发送不成功,我也不知道原因各参数都是正确的

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值