udp广播测试程序

2018-05-11  本文已影响0人  Timing_173a

本程序主要是为了熟悉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广播发送服务器,测试自动获取网卡的广播地址

上一篇下一篇

猜你喜欢

热点阅读