美文网首页
udp广播测试程序

udp广播测试程序

作者: Timing_173a | 来源:发表于2018-05-11 19:31 被阅读0次

    本程序主要是为了熟悉udp广播的测试程序,借鉴网上的程序

    #include <stdio.h>  
    #include <stdlib.h>  
    #include <unistd.h>  
    #include <string.h>  
    #include <sys/socket.h>  
    #include <netinet/in.h>  
    #include <sys/types.h>  
    #include <netdb.h>  
    #include <sys/ioctl.h>  
    #include <net/if.h>  
    
    #define CLIENT_PORT 8899
    
    #define DEBUF_CHECK(X, Y) \
        do{\
            if (X < 0){\
                perror(Y);\
                printf("%s %s %d %s error\r\n", __FILE__, __func__, __LINE__, Y);\
            }\
        }while(0)
    
    int main(int argc, char *argv[])
    {
        int ret;
        
        struct ifreq ifr; 
    
        int iSocket = socket(AF_INET, SOCK_DGRAM, 0);
        DEBUF_CHECK(iSocket, "create socket");
        printf("--------------\r\n");
        struct sockaddr_in server_addr;
        memset((char *)&server_addr, 0, sizeof(server_addr));
        server_addr.sin_family = AF_INET;
        server_addr.sin_port = htons(9999);
        server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        printf("-------1-------\r\n");
        ret = bind(iSocket, (struct sockaddr *)&server_addr, sizeof(struct sockaddr));
        DEBUF_CHECK(ret , "bind error");
        printf("-------2----%d---\r\n",sizeof(ifr.ifr_name));
        strcpy(ifr.ifr_name, "ens33"); //Currently, only get eth0
    
        printf("-------3-------\r\n");
        ret = ioctl(iSocket, SIOCGIFBRDADDR, &ifr);
        DEBUF_CHECK(ret , "ioctl error");
    
        struct sockaddr_in broadcast_addr;
        //memcpy(&broadcast_addr, (char *)&ifr->ifr_broadaddr, sizeof(struct sockaddr_in));  
        printf("-------3-------\r\n");
        broadcast_addr.sin_family = AF_INET;
        broadcast_addr.sin_port = htons(CLIENT_PORT);
        printf("-------4-------\r\n");
        //printf("\nBroadcast-IP: %s\r\n", inet_ntoa(broadcast_addr.sin_addr));  
        return 0;
    }
    

    以上程序主要用于测试ioctl函数是否正常运行,之前定义的struct ifreq *ifr;但是没有对ifr初始化,ioctl报错:error not found device。为了测试简单改为struct ifreq ifr

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <net/if.h>
    
    #define IP_FOUND "IP_FOUND"  
    #define IP_FOUND_ACK "IP_FOUND_ACK"  
    #define IFNAME "ens33"  
    #define MCAST_PORT 9999  
     
    void set_broadcast(int *socket_fd, struct sockaddr_in *broadcast_addr, char *buffer)
    {
        int j = 0;
        int ret;
        int so_broadcast = 1;  
        struct ifreq *ifr;  
        struct ifconf ifc;  
    
        int iSocket = *socket_fd;
        // 获取所有套接字接口  
    
        ifc.ifc_len = sizeof(buffer);  
        ifc.ifc_buf = buffer;  
    
        if (ioctl(iSocket, SIOCGIFCONF, (char *) &ifc) < 0)  
        {  
            perror("ioctl-conf:");  
            return;  
        }  
      
      // //查找当前网卡名
        ifr = ifc.ifc_req;  
      //   for (j = (ifc.ifc_len/sizeof(struct ifreq)); --j >= 0; ifr++)  
      //   {  
      //       if (!strcmp(ifr->ifr_name, "eth0"))  
      //       {  
      //           if (ioctl(iSocket, SIOCGIFFLAGS, (char *)ifr) < 0)  
      //           {  
      //               perror("ioctl-get flag failed:");  
      //           }  
      //           break;  
      //       }  
      //   }
        //指定固定的网卡执行
        strncpy(ifr->ifr_name, IFNAME, strlen(IFNAME)); 
        if (ioctl(iSocket, SIOCGIFBRDADDR, ifr) == -1)  
        {  
            perror("ioctl error");  
            return;  
        }  
    
        //将获得的广播地址复制到broadcast_addr  
        memcpy(broadcast_addr, (char *)&ifr->ifr_broadaddr, sizeof(struct sockaddr_in));  
        //设置广播端口号  
        printf("\nBroadcast-IP: %s\r\n", inet_ntoa(broadcast_addr->sin_addr));  
        broadcast_addr->sin_family = AF_INET;  
        broadcast_addr->sin_port = htons(8899);  
      //    broadcast_addr->sin_addr = inet_addr("192.168.0.255");
        //默认的套接字描述符sock是不支持广播,必须设置套接字描述符以支持广播  
       ret = setsockopt(iSocket, SOL_SOCKET, SO_BROADCAST, &so_broadcast,  
                sizeof(so_broadcast));  
        if(ret < 0)
        {
            perror("setsockopt error");
            return;
        }
    }
    
    int main(int argc, char* argv[])
    {
        int ret = -1;
        int iSocket = -1;
        int count;
        struct sockaddr_in server_addr; //服务器端地址  
        struct sockaddr_in client_addr; //客户端地址  
    
        struct timeval timeout;  
        char buffer[1024];
        int client_ilen = sizeof(struct sockaddr_in);
    
        iSocket = socket(AF_INET, SOCK_DGRAM, 0); //建立数据报套接字  
        if (iSocket == -1)
        {
            perror("iSocketet error");
            return -1;
        }
    
        memset((void*)&server_addr, 0, sizeof(struct sockaddr_in));  
        server_addr.sin_family = AF_INET;  
        server_addr.sin_addr.s_addr = htons(INADDR_ANY );  
        server_addr.sin_port = htons(MCAST_PORT);  
    
        set_broadcast(&iSocket, &client_addr, buffer);
        //将地址结构绑定到套接字上  
         ret = bind(iSocket, (struct sockaddr *)&server_addr, sizeof(server_addr));  
         if (ret < 0)  
         {  
            perror("bind error");  
            return -1;  
        }  
        printf("bind ok\r\n");
    
       
        fd_set readfd; //读文件描述符集合
        while(1)
        {
            timeout.tv_sec = 1000;  
            timeout.tv_usec = 0;  
    
            //文件描述符集合清0  
            FD_ZERO(&readfd);  
            //将套接字描述符加入到文件描述符集合  
            FD_SET(iSocket, &readfd);  
            //select侦听是否有数据到来  
            ret = select(iSocket + 1, &readfd, NULL, NULL, &timeout); //侦听是否可读 
            switch(ret)
            {
                case -1: //发生错误  
                    perror("select error:");  
                    break;  
                case 0: //超时  
                    printf("select timeout\n");  
                    break;  
                default:
                    if (FD_ISSET(iSocket, &readfd))  
                    {  
                        //count = recvfrom(iSocket, buffer, 1024, 0, (struct sockaddr *)&client_addr, &client_ilen); //接收客户端发送的数据  
                        count = recvfrom(iSocket, buffer, 1024, 0, NULL, NULL); //接收客户端发送的数据  
    
                
                        printf("recv count = %d\r\n", count);
                  
                         printf("\nClient connection information:\n\t IP: %s, Port: %d\n",  
                                    (char *)inet_ntoa(client_addr.sin_addr),  
                                     ntohs(client_addr.sin_port));  
    
                         //将数据发送给客户端  
                             memcpy(buffer, IP_FOUND_ACK, strlen(IP_FOUND_ACK) + 1);  
                             count = sendto(iSocket, buffer, strlen(buffer), 0,  
                                     (struct sockaddr *)&client_addr, client_ilen);  
                      
                    }  
            
            }
        }    
    
    }
    

    此程序是个简单udp广播发送服务器,测试自动获取网卡的广播地址

    相关文章

      网友评论

          本文标题:udp广播测试程序

          本文链接:https://www.haomeiwen.com/subject/lgkqdftx.html