Linux网络编程 之 UDP 广播 .

转载 2015年07月09日 11:20:35

在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。

这个倒让我花的时间最多了,主要一直脑残的在自己的虚拟机上调试不成功,认为只要开几个终端就可以当作服务器了,这种想法是错误的。因为ip地址会被占用的,所以后来我和同事测试一下,就OK了。

这个广播代码逻辑其实挺有用的,可以用来寻找所在局域网内设备

逻辑就是:客户端一直发广播,当服务器收到这个广播,则向客户端回个确认,这样客户端收到确认后就知道有所要的服务器了

  直接上代码吧,一个很简单udp 广播通信的例子,分别为服务器端和客户端的代码。


1、服务器代码 (bcast_server.c)

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /********************************************************************* 
  2.  * Filename: bcast_server.c 
  3.  * Description: 广播服务器端代码 
  4.  * Author: Eric(wongpz@foxmail.com) 
  5.  * Date: 2012-9-14 
  6.  ********************************************************************/  
  7. #include <stdio.h>  
  8. #include <string.h>  
  9. #include <sys/types.h>  
  10. #include <sys/socket.h>  
  11. #include <fcntl.h>  
  12. #include <linux/in.h>  
  13. #include <stdlib.h>  
  14.   
  15. #define IP_FOUND "IP_FOUND"  
  16. #define IP_FOUND_ACK "IP_FOUND_ACK"  
  17. #define PORT 9999  
  18.   
  19. int main(int argc, char*argv[])  
  20. {  
  21.     int ret = -1;  
  22.     int sock;  
  23.     struct sockaddr_in server_addr; //服务器端地址  
  24.     struct sockaddr_in from_addr; //客户端地址  
  25.     int from_len = sizeof(struct sockaddr_in);  
  26.     int count = -1;  
  27.     fd_set readfd; //读文件描述符集合  
  28.     char buffer[1024];  
  29.     struct timeval timeout;  
  30.     timeout.tv_sec = 2;  
  31.     timeout.tv_usec = 0;  
  32.   
  33.     sock = socket(AF_INET, SOCK_DGRAM, 0); //建立数据报套接字  
  34.     if (sock < 0)  
  35.     {  
  36.         perror("sock error");  
  37.         return -1;  
  38.     }  
  39.   
  40.     memset((void*) &server_addr, 0sizeof(struct sockaddr_in));  
  41.     server_addr.sin_family = AF_INET;  
  42.     server_addr.sin_addr.s_addr = htons(INADDR_ANY );  
  43.     server_addr.sin_port = htons(PORT);  
  44.   
  45.     //将地址结构绑定到套接字上  
  46.     ret = bind(sock, (struct sockaddr*) &server_addr, sizeof(server_addr));  
  47.     if (ret < 0)  
  48.     {  
  49.         perror("bind error");  
  50.         return -1;  
  51.     }  
  52.   
  53.     /** 
  54.      * 循环等待客户端 
  55.      */  
  56.     while (1)  
  57.     {  
  58.         timeout.tv_sec = 100;  
  59.         timeout.tv_usec = 0;  
  60.   
  61.         //文件描述符集合清0  
  62.         FD_ZERO(&readfd);  
  63.   
  64.         //将套接字描述符加入到文件描述符集合  
  65.         FD_SET(sock, &readfd);  
  66.   
  67.         //select侦听是否有数据到来  
  68.         ret = select(sock + 1, &readfd, NULLNULL, &timeout); //侦听是否可读  
  69.         switch (ret)  
  70.         {  
  71.         case -1//发生错误  
  72.             perror("select error:");  
  73.             break;  
  74.         case 0//超时  
  75.             printf("select timeout\n");  
  76.             break;  
  77.         default:  
  78.             if (FD_ISSET(sock,&readfd))  
  79.             {  
  80.                 count = recvfrom(sock, buffer, 10240,  
  81.                         (struct sockaddr*)&from_addr, &from_len); //接收客户端发送的数据  
  82.   
  83.                 //from_addr保存客户端的地址结构  
  84.                 if (strstr(buffer, IP_FOUND))  
  85.                 {  
  86.                     //响应客户端请求  
  87.                     //打印客户端的IP地址和端口号  
  88.                     printf("\nClient connection information:\n\t IP: %s, Port: %d\n",  
  89.                             (charchar *)inet_ntoa(from_addr.sin_addr),  
  90.                             ntohs(from_addr.sin_port));  
  91.   
  92.                     //将数据发送给客户端  
  93.                     memcpy(buffer, IP_FOUND_ACK, strlen(IP_FOUND_ACK) + 1);  
  94.                     count = sendto(sock, buffer, strlen(buffer), 0,  
  95.                             (struct sockaddr*) &from_addr, from_len);  
  96.                 }  
  97.             }  
  98.             break;  
  99.         }  
  100.     }  
  101.     return 0;  
  102. }  


2、客户端代码(bcast_clinet.c)

 

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. /********************************************************************* 
  2.  * Filename: bcast_client.c 
  3.  * Description:广播客户端代码 
  4.  * Author: Eric(wongpz@foxmail.com) 
  5.  * Date: 2012-9-14 
  6.  ********************************************************************/  
  7. #include<stdio.h>  
  8. #include<stdlib.h>  
  9. #include<unistd.h>  
  10. #include<string.h>  
  11. #include<sys/socket.h>  
  12. #include<arpa/inet.h>  
  13. #include<netinet/in.h>  
  14. #include<sys/types.h>  
  15. #include<netdb.h>  
  16. #include <sys/ioctl.h>  
  17. #include <net/if.h>  
  18.   
  19. #define IP_FOUND "IP_FOUND"  
  20. #define IP_FOUND_ACK "IP_FOUND_ACK"  
  21. #define IFNAME "eth0"  
  22. #define MCAST_PORT 9999  
  23.   
  24. int main(int argc, char*argv[])  
  25. {  
  26.     int ret = -1;  
  27.     int sock = -1;  
  28.     int j = -1;  
  29.     int so_broadcast = 1;  
  30.     struct ifreq *ifr;  
  31.     struct ifconf ifc;  
  32.     struct sockaddr_in broadcast_addr; //广播地址  
  33.     struct sockaddr_in from_addr; //服务端地址  
  34.     int from_len = sizeof(from_addr);  
  35.     int count = -1;  
  36.     fd_set readfd; //读文件描述符集合  
  37.     char buffer[1024];  
  38.     struct timeval timeout;  
  39.     timeout.tv_sec = 2//超时时间为2秒  
  40.     timeout.tv_usec = 0;  
  41.   
  42.     //建立数据报套接字  
  43.     sock = socket(AF_INET, SOCK_DGRAM, 0);  
  44.     if (sock < 0)  
  45.     {  
  46.         perror("create socket failed:");  
  47.         return -1;  
  48.     }  
  49.   
  50.     // 获取所有套接字接口  
  51.     ifc.ifc_len = sizeof(buffer);  
  52.     ifc.ifc_buf = buffer;  
  53.     if (ioctl(sock, SIOCGIFCONF, (charchar *) &ifc) < 0)  
  54.     {  
  55.         perror("ioctl-conf:");  
  56.         return -1;  
  57.     }  
  58.     ifr = ifc.ifc_req;  
  59.     for (j = ifc.ifc_len / sizeof(struct ifreq); --j >= 0; ifr++)  
  60.     {  
  61.         if (!strcmp(ifr->ifr_name, "eth0"))  
  62.         {  
  63.             if (ioctl(sock, SIOCGIFFLAGS, (charchar *) ifr) < 0)  
  64.             {  
  65.                 perror("ioctl-get flag failed:");  
  66.             }  
  67.             break;  
  68.         }  
  69.     }  
  70.   
  71.     //将使用的网络接口名字复制到ifr.ifr_name中,由于不同的网卡接口的广播地址是不一样的,因此指定网卡接口  
  72.     //strncpy(ifr.ifr_name, IFNAME, strlen(IFNAME));  
  73.     //发送命令,获得网络接口的广播地址  
  74.     if (ioctl(sock, SIOCGIFBRDADDR, ifr) == -1)  
  75.     {  
  76.         perror("ioctl error");  
  77.         return -1;  
  78.     }  
  79.     //将获得的广播地址复制到broadcast_addr  
  80.     memcpy(&broadcast_addr, (charchar *)&ifr->ifr_broadaddr, sizeof(struct sockaddr_in));  
  81.     //设置广播端口号  
  82.     printf("\nBroadcast-IP: %s\n", inet_ntoa(broadcast_addr.sin_addr));  
  83.     broadcast_addr.sin_family = AF_INET;  
  84.     broadcast_addr.sin_port = htons(MCAST_PORT);  
  85.   
  86.     //默认的套接字描述符sock是不支持广播,必须设置套接字描述符以支持广播  
  87.     ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &so_broadcast,  
  88.             sizeof(so_broadcast));  
  89.   
  90.     //发送多次广播,看网络上是否有服务器存在  
  91.     int times = 10;  
  92.     int i = 0;  
  93.     for (i = 0; i < times; i++)  
  94.     {  
  95.         //一共发送10次广播,每次等待2秒是否有回应  
  96.         //广播发送服务器地址请求  
  97.         timeout.tv_sec = 2;  //超时时间为2秒  
  98.         timeout.tv_usec = 0;  
  99.         ret = sendto(sock, IP_FOUND, strlen(IP_FOUND), 0,  
  100.                 (struct sockaddr*) &broadcast_addr, sizeof(broadcast_addr));  
  101.         if (ret < 0)  
  102.         {  
  103.             continue;  
  104.         }  
  105.   
  106.         //文件描述符清0  
  107.         FD_ZERO(&readfd);  
  108.         //将套接字文件描述符加入到文件描述符集合中  
  109.         FD_SET(sock, &readfd);  
  110.         //select侦听是否有数据到来  
  111.         ret = select(sock + 1, &readfd, NULLNULL, &timeout);  
  112.         switch (ret)  
  113.         {  
  114.         case -1:  
  115.             break;  
  116.         case 0:  
  117.             perror("select timeout\n");  
  118.             break;  
  119.         default:  
  120.             //接收到数据  
  121.             if (FD_ISSET(sock,&readfd))  
  122.             {  
  123.                 count = recvfrom(sock, buffer, 10240,  
  124.                         (struct sockaddr*) &from_addr, &from_len); //from_addr为服务器端地址  
  125.                 printf("\trecvmsg is %s\n", buffer);  
  126.                 if (strstr(buffer, IP_FOUND_ACK))  
  127.                 {  
  128.                     printf("\tfound server IP is %s, Port is %d\n",  
  129.                             inet_ntoa(from_addr.sin_addr),  
  130.                             htons(from_addr.sin_port));  
  131.                 }  
  132.                 return -1;  
  133.   
  134.             }  
  135.             break;  
  136.   
  137.         }  
  138.     }  
  139.     return 0;  
  140. }  

最后它的Makefile:

[objc] view plaincopy在CODE上查看代码片派生到我的代码片
  1. OBJS_SERVER = bcast_server.o  
  2. OBJS_CLIENT = bcast_client.o  
  3. LIBS_SERVER =   
  4. LIBS_CLIENT =   
  5.   
  6. CFLAGS = -c  
  7. CC = gcc  
  8.   
  9. PROS = bcast_client bcast_server  
  10.   
  11. all: $(PROS)  
  12.   
  13. .c.o:  
  14.     $(CC) $(CFLAGS) $<  
  15.   
  16. bcast_client: $(OBJS_CLIENT)  
  17.     $(CC) -o $@ $^ $(LIBS_SERVER)  
  18.   
  19. bcast_server: $(OBJS_SERVER)  
  20.     $(CC) -o $@ $^ $(LIBS_CLIENT)  
  21.   
  22. clean:  
  23.     rm -rf $(PROS) $(OBJS_CLIENT) $(OBJS_SERVER)  

运行效果如图:



linux网络编程源代码下载:http://download.csdn.net/detail/yanyuanfen2011/6595113


如有问题欢迎留言交流!

举报

相关文章推荐

Linux网络编程 之 UDP 广播 .

在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。 这个倒让我花的时间最多了,主要一直脑残的在自己的虚拟机上调试不成功,认为只要开几个终端就可以当作服务器了,这种想法是错误的。...

Linux网络编程 之 UDP 广播

最近一直在做linux的网络,现在作个总结,陆续贴出来。 在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。 这个倒让我花的时间最多了,主要一直脑残的在自己的虚拟机上调试不...

精选:深入理解 Docker 内部原理及网络配置

网络绝对是任何系统的核心,对于容器而言也是如此。Docker 作为目前最火的轻量级容器技术,有很多令人称道的功能,如 Docker 的镜像管理。然而,Docker的网络一直以来都比较薄弱,所以我们有必要深入了解Docker的网络知识,以满足更高的网络需求。

linux网络编程之广播编程

广播方式主要是指使用UDP套接口发送数据,发送数据的目标地址不是普通的地址,而是所指定网络的广播地址。  什么是广播地址?是指IP地址中主机地址部分全为1的IP地址。 下面是一个广播发送简...

【Linux网络编程】广播

概述 在生活中广播无处不在,像平时在大街上卖物品的商人,在进行推广产品的时候往往都是使用一个喇叭来进行吆喝:“十块钱买不了吃亏,十块钱买不了上当,走过路过千万不要错过”,这就是广播。 ...

Linux网络编程——广播

概述 在生活中广播无处不在,像平时在大街上卖物品的商人,在进行推广产品的时候往往都是使用一个喇叭来进行吆喝:“十块钱买不了吃亏,十块钱买不了上当,走过路过千万不要错过”,这就是广播。 ...

Linux网络编程——广播

在生活中广播无处不在,像平时在大街上卖物品的商人,在进行推广产品的时候往往都是使用一个喇叭来进行吆喝:“十块钱买不了吃亏,十块钱买不了上当,走过路过千万不要错过”,这就是广播。 那么在网络中的广播又是...

Linux网络编程 之 UDP 组播

最近一直在做linux的网络,现在作个总结,陆续贴出来。 在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。 直接上代码吧,一个很简单udp 组播通信的例子,分别为服务器端和...

Linux网络编程 之 UDP 单播

最近一直在做linux的网络,现在作个总结,陆续贴出来。 在网上搜了很多资料 ,其中周立发的博客对我的学习参考作用最大,谢谢前辈。 直接上代码吧,一个很简单udp通信的例子,分别为服务器端和客户端的...

Linux网络编程之广播

1.概念 前面介绍的TCP,UDP都是单播方式,即一对一.而广播是一台主机向局域网内的所有主机发送数据。这时,同一网段的所有主机都能接收到数据。发送广播包的步骤大致如下: (1)确定一个发送广播的...

linux网络编程:广播编程

概述 在生活中广播无处不在,像平时在大街上卖物品的商人,在进行推广产品的时候往往都是使用一个喇叭来进行吆喝:“十块钱买不了吃亏,十块钱买不了上当,走过路过千万不要错过”,这就是广播。 ...
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)