当前位置: 首页 > news >正文

linux udp广播数据包实际用例

1.说明

本节说明的是在实际案例中使用udp广播数据包产生的问题以及记录。

2.广播数据包服务端与客户端代码用例

2.1 服务端客户端广播数据包发送与接收

第一种场景,服务端部署在A机器,客户端部署在B机器。 服务端代码server.c,如下:

#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include <ifaddrs.h>
#include <net/if.h>#define UDP_NOTIFY_PORT  20000int udp_socket_server_init(struct sockaddr_in *saddr)
{int optval = 1, fd = -1;if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){printf("cannot setup socket \n");return -1;}if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0){printf("cannot set socket setting \n");close(fd);return -1;}// struct ifreq ifr;// memset(&ifr, 0, sizeof(ifr));// snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");// if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {		// 	printf("setsockopt fail\n");// }saddr->sin_family= AF_INET;saddr->sin_port=htons(UDP_NOTIFY_PORT);saddr->sin_addr.s_addr= htonl(INADDR_BROADCAST);if(-1 == bind(fd,(struct sockaddr *)saddr,sizeof(struct sockaddr))){printf("Failed to bind socket server\n");close(fd);return -1;}return fd;
}// unsigned char matchLocalIp(char *pSrcIp, int ipLen)
// {
//     struct ifaddrs *ifaddr, *ifa;
//     char ip[INET_ADDRSTRLEN];//     if(ip == NULL)
//         return 0;//     unsigned char findIp = 0;//     if (getifaddrs(&ifaddr) == -1) {
//         return findIp;
//     }
//     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
//         if (ifa->ifa_addr == NULL)
//             continue;
//         const int family = ifa->ifa_addr->sa_family;
//         if (family != AF_INET && family != AF_INET6) {
//             continue;
//         }  
//         const char *ifa_name = ifa->ifa_name;
//         printf("ifa name: %s\n", ifa_name);                       //         struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
//         inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN);
//         printf("interface: %s, IP: %s\n", ifa->ifa_name, ip);//         if((ipLen == strlen(ip)) && (strncmp(ip, pSrcIp, ipLen) == 0))
//         {
//             findIp = 1;
//         }
//     }//     freeifaddrs(ifaddr);//     return findIp;
// }int main()
{struct sockaddr_in udp_addr = {0}, addr_len = {0};int udp_fd = udp_socket_server_init(&udp_addr);if (udp_fd < 0) {printf("failed to init server\n");return -1;}int buffer = 0;socklen_t len = sizeof(addr_len);int n = 0;while (1) {memset(&buffer, 0, sizeof(buffer));n = 0;while (n <= 0 ) {printf("Start recvfrom form broadcast.\n");n = recvfrom(udp_fd, &buffer, sizeof(buffer), MSG_WAITALL,(struct sockaddr *)&udp_addr, &len);if (n <= 0) {printf("Error while receiving broadcast\n");continue;}printf("client IPAddr = %s, Port = %d\n", inet_ntoa(udp_addr.sin_addr), ntohs(udp_addr.sin_port));switch (buffer){case 0 :    // host reset event{//printf("client IPAddr = %s\n", (char * )inet_ntoa(udp_addr.sin_addr));n = -1; // continue with n <= 0 printf(" buffer = %d\n", buffer);// char *ip = inet_ntoa(udp_addr.sin_addr);// if(ip == NULL)// {//     continue;// }// if(matchLocalIp(ip,strlen(ip)) == 0)// {//     printf("from other device ,should ignore.\n");// }// else// {//     printf("from self device ,should not ignore.\n");// }}break;case 1 :{printf("[line:%d] Received broadcast, buffer = %d\n", __LINE__,buffer);}break;default :{printf("[line:%d] Received broadcast, buffer = %d\n", __LINE__,buffer);}   break;}             }}    return 0;
}

客户端代码client.c,如下:

#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>#define UDP_NOTIFY_PORT  20000int Socket;
struct sockaddr_in SockAddr;int udp_socket_client_init()
{int optval = 1;struct ifreq ifr;if((Socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0){printf("cannot setup socket \n");return -1;}if(fcntl(Socket,F_SETFL,O_NONBLOCK) < 0){printf("cannot set IO mechanism \n");close(Socket);return -1;}if(setsockopt(Socket,SOL_SOCKET,SO_BROADCAST|SO_REUSEADDR,&optval,sizeof(int)) < 0){printf("cannot set socket setting \n");close(Socket);return -1;}// memset(&ifr, 0, sizeof(ifr));// snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");// if (setsockopt(Socket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {		// 	printf("setsockopt fail\n");// }	SockAddr.sin_family= AF_INET;SockAddr.sin_port=htons(UDP_NOTIFY_PORT);SockAddr.sin_addr.s_addr= inet_addr("255.255.255.255");
}void UDPNotify(int initialized)
{int retval = 0;int event[1] = {initialized};socklen_t len = sizeof(struct sockaddr);int ret = 0;retval = sendto(Socket, event, 1, 0, (struct sockaddr *)&SockAddr, len);if(retval < 0){printf("Fail to broadcast\n");}
}int main()
{udp_socket_client_init();UDPNotify(1);return 0;
}

分别在A机器与B机器编译执行:

# gcc server.c -o server  //A机器
# ./server                //A机器
# gcc client.c -o client  //B机器
# ./client

A机器服务端打印结果如下:

在这里插入图片描述
或者在B机器执行如下命令:

# echo "1" | socat - UDP4-DATAGRAM:255.255.255.255:20000,broadcast

打印数据如下:

在这里插入图片描述

可以在A机器部署2个服务端,可以看到如下打印:

在这里插入图片描述

2.2 客户端本机广播数据包

客户端可以绑定本机,只在本机广播数据包,而不是广播到整个局域网。

客户端代码client.c如下,绑定lo网络设备:

#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>#define UDP_NOTIFY_PORT  20000int Socket;
struct sockaddr_in SockAddr;int udp_socket_client_init()
{int optval = 1;struct ifreq ifr;if((Socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0){printf("cannot setup socket \n");return -1;}if(fcntl(Socket,F_SETFL,O_NONBLOCK) < 0){printf("cannot set IO mechanism \n");close(Socket);return -1;}if(setsockopt(Socket,SOL_SOCKET,SO_BROADCAST|SO_REUSEADDR,&optval,sizeof(int)) < 0){printf("cannot set socket setting \n");close(Socket);return -1;}memset(&ifr, 0, sizeof(ifr));snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");if (setsockopt(Socket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {		printf("setsockopt fail\n");}	SockAddr.sin_family= AF_INET;SockAddr.sin_port=htons(UDP_NOTIFY_PORT);SockAddr.sin_addr.s_addr= inet_addr("255.255.255.255");
}void UDPNotify(int initialized)
{int retval = 0;int event[1] = {initialized};socklen_t len = sizeof(struct sockaddr);int ret = 0;retval = sendto(Socket, event, 1, 0, (struct sockaddr *)&SockAddr, len);if(retval < 0){printf("Fail to broadcast\n");}
}int main()
{udp_socket_client_init();UDPNotify(1);return 0;
}

这个时候仍将客户端部署在B机器上,执行之后,可以看到A机器(服务端)不会收到客户端数据包

那么将客户端部署到A机器上,(客户端与服务端在一台机器上),这个时候可以看到服务端能收到客户端的数据包。

2.3 服务端本机广播数据包

修改服务端server.c代码如下,绑定lo网络设备:

#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <arpa/inet.h>#include <ifaddrs.h>
#include <net/if.h>#define UDP_NOTIFY_PORT  20000int udp_socket_server_init(struct sockaddr_in *saddr)
{int optval = 1, fd = -1;if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){printf("cannot setup socket \n");return -1;}if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(int)) < 0){printf("cannot set socket setting \n");close(fd);return -1;}struct ifreq ifr;memset(&ifr, 0, sizeof(ifr));snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");if (setsockopt(fd, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {		printf("setsockopt fail\n");}saddr->sin_family= AF_INET;saddr->sin_port=htons(UDP_NOTIFY_PORT);saddr->sin_addr.s_addr= htonl(INADDR_BROADCAST);if(-1 == bind(fd,(struct sockaddr *)saddr,sizeof(struct sockaddr))){printf("Failed to bind socket server\n");close(fd);return -1;}return fd;
}// unsigned char matchLocalIp(char *pSrcIp, int ipLen)
// {
//     struct ifaddrs *ifaddr, *ifa;
//     char ip[INET_ADDRSTRLEN];//     if(ip == NULL)
//         return 0;//     unsigned char findIp = 0;//     if (getifaddrs(&ifaddr) == -1) {
//         return findIp;
//     }
//     for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
//         if (ifa->ifa_addr == NULL)
//             continue;
//         const int family = ifa->ifa_addr->sa_family;
//         if (family != AF_INET && family != AF_INET6) {
//             continue;
//         }  
//         const char *ifa_name = ifa->ifa_name;
//         printf("ifa name: %s\n", ifa_name);                       //         struct sockaddr_in *addr = (struct sockaddr_in *)ifa->ifa_addr;
//         inet_ntop(AF_INET, &addr->sin_addr, ip, INET_ADDRSTRLEN);
//         printf("interface: %s, IP: %s\n", ifa->ifa_name, ip);//         if((ipLen == strlen(ip)) && (strncmp(ip, pSrcIp, ipLen) == 0))
//         {
//             findIp = 1;
//         }
//     }//     freeifaddrs(ifaddr);//     return findIp;
// }int main()
{struct sockaddr_in udp_addr = {0}, addr_len = {0};int udp_fd = udp_socket_server_init(&udp_addr);if (udp_fd < 0) {printf("failed to init server\n");return -1;}int buffer = 0;socklen_t len = sizeof(addr_len);int n = 0;while (1) {memset(&buffer, 0, sizeof(buffer));n = 0;while (n <= 0 ) {printf("Start recvfrom form broadcast.\n");n = recvfrom(udp_fd, &buffer, sizeof(buffer), MSG_WAITALL,(struct sockaddr *)&udp_addr, &len);if (n <= 0) {printf("Error while receiving broadcast\n");continue;}printf("client IPAddr = %s, Port = %d\n", inet_ntoa(udp_addr.sin_addr), ntohs(udp_addr.sin_port));switch (buffer){case 0 :    // host reset event{//printf("client IPAddr = %s\n", (char * )inet_ntoa(udp_addr.sin_addr));n = -1; // continue with n <= 0 printf(" buffer = %d\n", buffer);// char *ip = inet_ntoa(udp_addr.sin_addr);// if(ip == NULL)// {//     continue;// }// if(matchLocalIp(ip,strlen(ip)) == 0)// {//     printf("from other device ,should ignore.\n");// }// else// {//     printf("from self device ,should not ignore.\n");// }}break;case 1 :{printf("[line:%d] Received broadcast, buffer = %d\n", __LINE__,buffer);}break;default :{printf("[line:%d] Received broadcast, buffer = %d\n", __LINE__,buffer);}   break;}             }}    return 0;
}

客户端仍然部署在B机器上,但是可以广播到局域网,client.c代码如下:

#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>#define UDP_NOTIFY_PORT  20000int Socket;
struct sockaddr_in SockAddr;int udp_socket_client_init()
{int optval = 1;struct ifreq ifr;if((Socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0){printf("cannot setup socket \n");return -1;}if(fcntl(Socket,F_SETFL,O_NONBLOCK) < 0){printf("cannot set IO mechanism \n");close(Socket);return -1;}if(setsockopt(Socket,SOL_SOCKET,SO_BROADCAST|SO_REUSEADDR,&optval,sizeof(int)) < 0){printf("cannot set socket setting \n");close(Socket);return -1;}// memset(&ifr, 0, sizeof(ifr));// snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");// if (setsockopt(Socket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {		// 	printf("setsockopt fail\n");// }	SockAddr.sin_family= AF_INET;SockAddr.sin_port=htons(UDP_NOTIFY_PORT);SockAddr.sin_addr.s_addr= inet_addr("255.255.255.255");
}void UDPNotify(int initialized)
{int retval = 0;int event[1] = {initialized};socklen_t len = sizeof(struct sockaddr);int ret = 0;retval = sendto(Socket, event, 1, 0, (struct sockaddr *)&SockAddr, len);if(retval < 0){printf("Fail to broadcast\n");}
}int main()
{udp_socket_client_init();UDPNotify(1);return 0;
}

可以看到A服务端是收不到B客户端的数据的。

将客户端部署在A机器上,然后绑定lo设备:

#include <unistd.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>#define UDP_NOTIFY_PORT  20000int Socket;
struct sockaddr_in SockAddr;int udp_socket_client_init()
{int optval = 1;struct ifreq ifr;if((Socket = socket(AF_INET, SOCK_DGRAM, 0)) < 0){printf("cannot setup socket \n");return -1;}if(fcntl(Socket,F_SETFL,O_NONBLOCK) < 0){printf("cannot set IO mechanism \n");close(Socket);return -1;}if(setsockopt(Socket,SOL_SOCKET,SO_BROADCAST|SO_REUSEADDR,&optval,sizeof(int)) < 0){printf("cannot set socket setting \n");close(Socket);return -1;}memset(&ifr, 0, sizeof(ifr));snprintf(ifr.ifr_name, sizeof(ifr.ifr_name), "lo");if (setsockopt(Socket, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0) {		printf("setsockopt fail\n");}	SockAddr.sin_family= AF_INET;SockAddr.sin_port=htons(UDP_NOTIFY_PORT);SockAddr.sin_addr.s_addr= inet_addr("255.255.255.255");
}void UDPNotify(int initialized)
{int retval = 0;int event[1] = {initialized};socklen_t len = sizeof(struct sockaddr);int ret = 0;retval = sendto(Socket, event, 1, 0, (struct sockaddr *)&SockAddr, len);if(retval < 0){printf("Fail to broadcast\n");}
}int main()
{udp_socket_client_init();UDPNotify(1);return 0;
}

A服务端能收到数据。
在这里插入图片描述
因此,服务端与客户端均绑定lo设备,广播数据包将不会扩散到局域网以及服务端不会收到来自局域网的数据包。

http://www.dtcms.com/a/569542.html

相关文章:

  • 什么公司需要建立网站电商平台运营策略
  • 厦门怎么没有 网站备案wordpress网站的彻底清理
  • 一文讲全volatile关键字
  • 西安高校网站建设保定手机网站制作
  • 对称加密与非对称加密
  • Swift添加字体到项目中
  • 大专建筑工程技术专业职业发展指南
  • 免费免费网站模板企业调查问卷
  • 考研408--day2--组成原理--进制定点数符号拓展
  • 硬件工程师-基础知识电阻(一)
  • 13-- System Coherency Interface
  • 用代码示例说明如何通过线程池实现Java多线程编程
  • 网易做网站企业怎么在网站上做宣传
  • 响应式网站制作工具搜了网
  • [Android] 人事考试网v1.0.4
  • Python 面向对象
  • 技术解析:佐航BYQ3313S手持式三相直阻测试仪如何重塑多场景变压器检测价值
  • RuoyiApp 在vuex,state存储nickname vue2
  • 常见的网站类型有哪些wordpress收费会员
  • 建设银行成都开发中心网站saas云建站
  • 视频网站如何做爱奇艺做任务领vip网站
  • 用python可视化分析上海教育中考新政
  • MySQL的UPPER函数介绍
  • 自己搭建一个网站我做钓鱼网站自首了
  • 专用主机方式建设网站用discuz做的大网站
  • [特殊字符] Java/Vue 实现体育比分直播系统,支持多端实时更新
  • 沈阳哪个网站建设公司好重庆网站制作一般多少钱
  • 用vscode连接远端ubuntu无法git push,vscode无法连接centos
  • 商业门户网站怎么运营淘宝关键词怎么选取
  • oj 素数个数 难