广播
范围: 仅局域网
/**
* @name server.c
* @author IYATT-yx
* @brief UDP广播 - 服务器端
*/
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
{
perror("socket error");
exit(EXIT_FAILURE);
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(11111);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr *)&server, sizeof(server)))
{
perror("bind error");
exit(EXIT_FAILURE);
}
// 初始化客户端地址信息
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(11112);
// 使用广播地址给客户端发数据
inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr);
// 打开广播权限
int flag = 1;
setsockopt(AF_INET, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag));
while (true)
{
// 发送广播
static int counter = 0;
char buf[1024] = {0};
sprintf(buf, "%d 广播中...", ++counter);
if (sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&client, sizeof(client)) == -1)
{
perror("sendto error");
exit(EXIT_FAILURE);
}
printf("已广播内容: %s\n", buf);
sleep(1);
}
close (fd);
}
/**
* @name client.c
* @author IYATT-yx
* @brief UDP广播 - 客户端
*/
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
int main(void)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
{
perror("socket error");
exit(EXIT_FAILURE);
}
// 绑定IP和端口
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(11112);
if (inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr) == -1)
{
perror("inet_pton error");
exit(EXIT_FAILURE);
}
if (bind(fd, (struct sockaddr *)&client, sizeof(client)) == -1)
{
perror("bind error");
exit(EXIT_FAILURE);
}
while (true)
{
char buf[1024] = {0};
if (recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL) == -1)
{
perror("recvfrom error");
exit(EXIT_FAILURE);
}
printf("收到广播内容: %s\n", buf);
}
close(fd);
}
组播 (多播)
范围: 局域网和Internet
224.0.0.0 ~ 224.0.0.255 | 预留的组播地址 (永久组地址), 地址224.0.0.0保留不做分配, 其它地址供路由协议使用 |
224.0.1.0 ~ 224.0.1.255 | 公用组播地址, 可以用于Internet; 需申请. |
224.0.2.0 ~ 238.255.255.255 | 用户可用的组播地址 (临时组地址), 全网范围内有效 |
239.0.0.0 ~ 239.255.255.255 | 本地管理组播地址, 仅在特定的本地范围内有效 |
struct ip_mreqn
{
// 多播组的IP地址
struct in_addr imr_multiaddr;
// 本地某一网络设备接口的IP地址
struct in_addr imr_interface;
// 网卡编号
int imr_ifindex;
};
struct in_addr
{
in_addr_t s_addr;
};
/**
* @name server.c
* @author IYATT-yx
* @brief UDP组播 - 服务器端
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <ifaddrs.h>
int main(void)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
{
perror("socket error");
exit(EXIT_FAILURE);
}
struct sockaddr_in server;
server.sin_family = AF_INET;
server.sin_port = htons(11111);
server.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(fd, (struct sockaddr *)&server, sizeof(server)))
{
perror("bind error");
exit(EXIT_FAILURE);
}
// 初始化客户端地址信息
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(11112);
// 使用组播地址给客户端发数据
inet_pton(AF_INET, "239.0.0.100", &client.sin_addr.s_addr);
// 打开组播权限
struct ip_mreqn flag;
inet_pton(AF_INET, "239.0.0.100", &flag.imr_multiaddr.s_addr);
inet_pton(AF_INET, "0.0.0.0", &flag.imr_address.s_addr);
// 获取网卡名,然后用网卡名获取接口号
struct ifaddrs *ifAddrStruct = NULL;
getifaddrs(&ifAddrStruct);
char name[10];
while (ifAddrStruct != NULL)
{
if (strcmp(ifAddrStruct->ifa_name, "lo") != 0)
{
strcpy(name, ifAddrStruct->ifa_name);
break;
}
ifAddrStruct = ifAddrStruct->ifa_next;
}
char chIdx[3];
sprintf(chIdx, "%d", if_nametoindex(name));
int intIdx = atoi(chIdx);
flag.imr_ifindex = intIdx;
setsockopt(AF_INET, IPPROTO_IP, IP_MULTICAST_IF, &flag, sizeof(flag));
while (true)
{
// 发送
static int counter = 0;
char buf[1024] = {0};
sprintf(buf, "%d 运行中...", ++counter);
if (sendto(fd, buf, strlen(buf) + 1, 0, (struct sockaddr *)&client, sizeof(client)) == -1)
{
perror("sendto error");
exit(EXIT_FAILURE);
}
printf("已发送内容: %s\n", buf);
sleep(1);
}
close (fd);
}
/**
* @name client.c
* @author IYATT-yx
* @brief UDP组播 - 客户端
*/
#define _GNU_SOURCE
#include <sys/socket.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>
#include <net/if.h>
#include <ifaddrs.h>
int main(void)
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if (fd == -1)
{
perror("socket error");
exit(EXIT_FAILURE);
}
// 绑定IP和端口
struct sockaddr_in client;
client.sin_family = AF_INET;
client.sin_port = htons(11112);
if (inet_pton(AF_INET, "0.0.0.0", &client.sin_addr.s_addr) == -1)
{
perror("inet_pton error");
exit(EXIT_FAILURE);
}
if (bind(fd, (struct sockaddr *)&client, sizeof(client)) == -1)
{
perror("bind error");
exit(EXIT_FAILURE);
}
struct ip_mreqn flag;
inet_pton(AF_INET, "239.0.0.100", &flag.imr_multiaddr.s_addr);
inet_pton(AF_INET, "0.0.0.0", &flag.imr_address.s_addr);
// 获取网卡名,然后用网卡名获取接口号
struct ifaddrs *ifAddrStruct = NULL;
getifaddrs(&ifAddrStruct);
char name[10];
while (ifAddrStruct != NULL)
{
if (strcmp(ifAddrStruct->ifa_name, "lo") != 0)
{
strcpy(name, ifAddrStruct->ifa_name);
break;
}
ifAddrStruct = ifAddrStruct->ifa_next;
}
char chIdx[3];
sprintf(chIdx, "%d", if_nametoindex(name));
int intIdx = atoi(chIdx);
flag.imr_ifindex = intIdx;
setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &flag, sizeof(flag));
while (true)
{
char buf[1024] = {0};
if (recvfrom(fd, buf, sizeof(buf), 0, NULL, NULL) == -1)
{
perror("recvfrom error");
exit(EXIT_FAILURE);
}
printf("收到组播内容: %s\n", buf);
}
close(fd);
}