UDP 广播机制

来源:互联网 发布:淘宝淘工作 兼职可信吗 编辑:程序博客网 时间:2024/05/20 01:34

UDP 

1,简介

UDP 为用户数据包协议,它的头为8byte数据;分别为16bit源端口号,16bit目的端口号,16bit长度,16bit校验和;它为无连接,主要用于视频传输相关的应用;因为

客户比较关注实时性; 它不需像TCP 那样,在发送数据前需建立连接; 


2,基于udp 广播的client server端实例:

client:#include <stdio.h>#include <sys/socket.h>#include <unistd.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <linux/if.h>#include <sys/ioctl.h>#include <errno.h>#define DDPAI_FOUND      "DDPAI_FOUND"#define DDPAI_FOUND_ACK  "DDPAI_FOUND_ACK"#define IFNAME "wlan0"#define MCAST_PORT  8888int main(int argc, char **argv){    int socketFd = -1;    int lRtn = -1;    struct sockaddr_in destAddr;    struct sockaddr_in sourAddr;        /*创建数据报套接字*/    socketFd = socket(AF_INET,SOCK_DGRAM,0);    if(socketFd < 0)    {        printf("socket error:%d\n",errno);        return -1;    }          /*设置源地址为本地广播地址*/    bzero(&sourAddr,sizeof(struct sockaddr_in));    sourAddr.sin_family = AF_INET;    sourAddr.sin_addr.s_addr = htonl(INADDR_BROADCAST);    sourAddr.sin_port = htons(MCAST_PORT);    const int broadcastOpt = 1;    /*设置套接字为广播类型*/    lRtn = setsockopt(socketFd,SOL_SOCKET,SO_BROADCAST,(char *)&broadcastOpt,sizeof(broadcastOpt));    if(lRtn < 0)    {        printf("set socket broadcast error:%d\n",errno);        close(socketFd);        return -1;    }    /*设置套接字 发送/接收缓冲区 属性*/    const int nSendBuf = 0;    lRtn = setsockopt(socketFd,SOL_SOCKET,SO_SNDBUF,(char *)&nSendBuf,sizeof(int));    if(lRtn < 0)    {        close(socketFd);        printf("setsockopt SO_SNDBUF error\n");        return -1;        }    const int nRcvBuf = 0;    lRtn = setsockopt(socketFd,SOL_SOCKET,SO_RCVBUF,(char *)&nRcvBuf,sizeof(int));    if(lRtn < 0)    {        close(socketFd);        printf("setsockopt SO_RCVBUF error\n");        return -1;        }    int lSize = sizeof(destAddr);    fd_set rFdSet;    struct timeval tv;    sleep(1);    int idx = 0;    for(idx = 0; idx < 5; idx++)    {        lRtn = sendto(socketFd,DDPAI_FOUND,strlen(DDPAI_FOUND),0,(struct sockaddr *)&sourAddr,lSize);        if(lRtn < 0)        {            printf("sendto error:%d\n",errno);            close(socketFd);            return -1;        }        printf("[client] send %d byte file ok \n",lRtn);    }    while(1)    {        FD_ZERO(&rFdSet);        FD_SET(socketFd,&rFdSet);        tv.tv_sec = 1;        tv.tv_usec = 0;        printf("[client] %s %d\n",__func__,__LINE__);        lRtn = select(socketFd+1,&rFdSet,NULL,NULL,&tv);        if(lRtn < 0)        {            printf("select error\n");            close(socketFd);            return -1;           }        else if(lRtn == 0)        {            usleep(100000);            printf("timeout\n");            continue;        }        else        {            if(FD_ISSET(socketFd,&rFdSet))            {                char msg[128] = {0x00};                lRtn = recvfrom(socketFd,msg,128,0,(struct sockaddr*)&destAddr,(socklen_t *)&lSize);                if(lRtn <= 0)                {                    printf("recvfrom error\n");                }                else                {                    printf("recv %d byte data:%s\n",lRtn,msg);                    if(NULL != strstr(msg,DDPAI_FOUND_ACK))                    {                        printf("server ip:%s msg:%s\n",inet_ntoa(destAddr.sin_addr),msg);                                      }                }            }            usleep(500000);        }        }    close(socketFd);    return 0;}

server:#include <stdio.h>#include <stdlib.h>#include <sys/socket.h>#include <unistd.h>#include <string.h>#include <netinet/in.h>#include <arpa/inet.h>#include <linux/if.h>#include <sys/ioctl.h>#include "errno.h"#define DDPAI_FOUND      "DDPAI_FOUND"#define DDPAI_FOUND_ACK  "DDPAI_FOUND_ACK"#define MCAST_PORT  8888#define IFNAME "wlan0"#define IPADDR_SIZE 32struct interface_info{    char ip_addr[IPADDR_SIZE];    char broad_addr[IPADDR_SIZE];    char mask_addr[IPADDR_SIZE];    char mac_addr[IPADDR_SIZE];};void freeMem(void *pFree){    free(pFree);    pFree = NULL;}int getLocalInterfaceInfo(struct interface_info *if_info){ #define INET_ADDRSRLEN  128    int sockFd = -1;    int lRtn = -1;    struct ifreq ifr;    struct sockaddr_in *addr;        if((sockFd = socket(AF_INET,SOCK_DGRAM,0)) < 0)    {        printf("%s create socket error\n",__func__);        return -1;    }    strncpy(&ifr.ifr_name,IFNAME,strlen(IFNAME));    /*获取ip address*/    lRtn = ioctl(sockFd,SIOCGIFADDR,&ifr);    if(lRtn < 0)    {        printf("ioctl SIOCGIFADDR error:%d\n",errno);        close(sockFd);        return -1;    }    /*获取广播地址*/    addr = (struct sockaddr_in *)&(ifr.ifr_addr);    sprintf(if_info->ip_addr,"%s",inet_ntoa(addr->sin_addr));    printf("ipaddr:%s\n",if_info->ip_addr);    lRtn = ioctl(sockFd,SIOCGIFBRDADDR,&ifr);    if(lRtn < 0)    {        printf("ioctl SIOCGIFBRDADDR error:%d\n",errno);        close(sockFd);        return -1;    }    /*获取子网掩码*/    addr = (struct sockaddr_in *)&(ifr.ifr_broadaddr);    sprintf(if_info->broad_addr,"%s",inet_ntoa(addr->sin_addr));    printf("broad_addr:%s\n",if_info->broad_addr);    lRtn = ioctl(sockFd,SIOCGIFNETMASK,&ifr);    if(lRtn < 0)    {        printf("ioctl SIOCGIFNETMASK error:%d\n",errno);        close(sockFd);        return -1;    }    /*获取MAC地址*/    addr = (struct sockaddr_in *)&(ifr.ifr_addr);    sprintf(if_info->mask_addr,"%s",inet_ntoa(addr->sin_addr));    printf("mask_addr:%s\n",if_info->mask_addr);    lRtn = ioctl(sockFd,SIOCGIFHWADDR,&ifr);    if(lRtn < 0)    {        printf("ioctl SIOCGIFHWADDR error:%d\n",errno);        close(sockFd);        return -1;    }    unsigned char *hw = (unsigned char *)ifr.ifr_hwaddr.sa_data;    sprintf(if_info->mac_addr,"%2x:%2x:%2x:%2x:%2x:%2x",                              hw[0],hw[1],hw[2],hw[3],hw[4],hw[5]);    printf("macAddr:%s\n",if_info->mac_addr);    close(sockFd);    return 0;   }int main(int argc, char **argv){#define BUS_SIZE 64    int socketFd = -1;    int lRtn = -1;    int lSize = 0;    char buf[BUS_SIZE] = {0x00};    fd_set rFdSet;    struct timeval tv;    struct sockaddr_in destAddr;  /*远端发送广播包地址*/     struct sockaddr_in sourAddr;  /*绑定本地地址*/    struct interface_info *if_info;        /*    *    通用socket地址:    *    struct sockaddr    *    {    *       sa_family_t sa_family; 地址族类型    *       char sa_data[14];             *     }    *     协议族             地址族       描述     *     PF_UNIX            AF_UNIX      UNIX本地域协议族    *     PF_INET            AF_INET      TCP/IPv4协议族    *     PF_INET6           AF_INET6     TCP/IPv6协议族    */    if_info = (struct interface_info *)malloc(sizeof(struct interface_info));    if(NULL == if_info)    {        printf("malloc error\n");        return -1;    }    /*绑定本地地址*/    bzero(&sourAddr,sizeof(struct sockaddr_in));    sourAddr.sin_family = AF_INET;    sourAddr.sin_addr.s_addr = htonl(INADDR_ANY);    sourAddr.sin_port = htons(MCAST_PORT);    /*创建数据报套接字*/    socketFd = socket(AF_INET,SOCK_DGRAM,0);    if(socketFd < 0)    {        printf("socket error:%d\n",errno);        freeMem(if_info);        return -1;    }    const int broadcastOpt = 1;    /*设置套接字为广播类型*/    lRtn = setsockopt(socketFd,SOL_SOCKET,SO_BROADCAST,(char *)&broadcastOpt,sizeof(broadcastOpt));    if(lRtn < 0)    {        printf("set socket broadcast error:%d\n",errno);        close(socketFd);        freeMem(if_info);        return -1;    }    /* 设置套接字发送缓冲区大小为2K */    const int nSendBuf = 2*1024;    lRtn = setsockopt(socketFd,SOL_SOCKET,SO_SNDBUF,(char *)&nSendBuf,sizeof(int));    if(lRtn < 0)    {        close(socketFd);        freeMem(if_info);        printf("setsockopt SO_SNDBUF error\n");        return -1;        }    /*设置套接字接收缓冲区大小为2K*/    const int nRcvBuf = 2*1024;    lRtn = setsockopt(socketFd,SOL_SOCKET,SO_RCVBUF,(char *)&nRcvBuf,sizeof(int));    if(lRtn < 0)    {        close(socketFd);        freeMem(if_info);        printf("setsockopt SO_RCVBUF error\n");        return -1;        }    /*绑定套接字*/    lRtn = bind(socketFd,(struct sockaddr *)&sourAddr,sizeof(struct sockaddr_in));    if(lRtn < 0)    {        printf("bind error :%d\n",errno);        close(socketFd);        freeMem(if_info);        return -1;    }   // getLocalInterfaceInfo(if_info);    lSize = sizeof(destAddr);    tv.tv_sec = 1;    tv.tv_usec = 0;    printf("[server] start recv data\n");    while(1)    {        FD_ZERO(&rFdSet);        FD_SET(socketFd,&rFdSet);                /*监听socketFd*/        lRtn = select(socketFd+1,&rFdSet,NULL,NULL,&tv);        if(lRtn < 0)        {            printf("select error\n");            close(socketFd);            freeMem(if_info);            return -1;           }        else if(lRtn == 0)        {            usleep(100000);            continue;        }        else        {            if(FD_ISSET(socketFd,&rFdSet))            {                char msg[128] = {0x00};                lRtn = recvfrom(socketFd,msg,128,0,(struct sockaddr*)&destAddr,(socklen_t *)&lSize);                if(lRtn <= 0)                {                    printf("recvfrom error\n");                }                else                {                    printf("recv %d byte data:%s\n",lRtn,msg);                    if(NULL != strstr(msg,DDPAI_FOUND))                    {                       // memcpy(buf,DDPAI_FOUND_ACK,strlen(DDPAI_FOUND_ACK)+1);                       // sprintf(buf,"%s:%s",DDPAI_FOUND_ACK,if_info->ip_addr);                        printf("[server] peer_ip:%s\n",inet_ntoa(destAddr.sin_addr));                        lRtn = sendto(socketFd,DDPAI_FOUND_ACK,strlen(DDPAI_FOUND_ACK),0,(struct sockaddr *)&destAddr,(socklen_t)lSize);                        if(lRtn < 0)                        {                            printf("sendto error:%d\n",errno);                            freeMem(if_info);                            close(socketFd);                            return -1;                        }                    }                }            }            usleep(500000);        }    }    close(socketFd);    freeMem(if_info);    return 0;} 


该简单实例通过测试,在局域网中正常接收到client 端发送过来的广播包;主要需要注意点:

#1 需创建SOCK_DGRAM

#2 设置socket为广播属性SO_BROADCAST

#2 sendto /rcvfrom 绑定的地址 ,传入的参数


仅供参考,相互学习,有什么错误的地方以及优化的地方请指出;

0 0