问题:如何进行一对多的 UDP 数据发送?
UDP 通讯中的广播
- 广播是向同一网络中的所有主机传输数据的方法
广播类型
- 直接广播:IP 地址中除网络地址外,其余主机地址均设置为 1
- 本地广播:无需知道网络,使用 255.255.255.255 作为 IP 地址使用
区别
本地广播数据不经过路由器寻址,直接发送到本地主机
本地广播应用案例:DHCP
DHCP (动态主机配置协议)是一个局域网的网络协议(基于 UDP 协议)
- 本地主机可自动获得服务器分配的 IP 地址和子网掩码
DHCP 采用 客户端 / 服务器 模型,地址的动态分配由网络主机驱动
工作方式:
- DHCP 服务器接收到来自网络主机的地址申请时,会向网络主机发送相关的地址配置信息,以实现网络主机地址信息的动态配置
预备准备 socket 属性设置(option)
- socket 的本质是对本机网络资源的一种标识
- socket 本身有各种属性(不同的连接,属性可能不同)
- 通过 setsockopt() / getsockopt() 可存取指定 socket 的属性值
- socket 属性的改变可造成 socket 数据收发行为的改变
TCP 编程中设计的用法
setsockopt() / getsockopt() 属性存取函数
#include
#include
int setsockopt(int sockfd,
int level,
int optname,
const void *optval,
socklen_t optlen);
int getsockopt(int sockfd,
int level,
int optname,
void *optval,
socklen_t *optlen);
若无错误发生返回 0; 否则返回 SOCKET_ERROR 错误。
UDP 数据广播
int sock = socket(PF_INET, SOCK_DGRAM, 0);
int brd = 1; // broadcast option flag
// ...
// ...
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, 0, &brd, sizeof(brd));
编程实验:UDP 数据广播
server.c
#include
#include
#include
#include
#include
#include
#include
int main()
{
int server = 0;
struct sockaddr_in saddr = {0};
int client = 0;
struct sockaddr_in remote = {0};
socklen_t asize = 0;
int len = 0;
char buf[32] = {0};
int r = 0;
server = socket(PF_INET, SOCK_DGRAM, 0);
if (server == -1) {
printf("server socket error");
return -1;
}
saddr.sin_family = AF_INET;
saddr.sin_addr.s_addr = htonl(INADDR_ANY);
saddr.sin_port = htons(8888);
if (bind(server, (struct sockaddr*)&saddr, sizeof(saddr)) == -1) {
printf("udp server bind error\n");
return -1;
}
printf("udp server start sucess\n");
while (1) {
len = sizeof(remote);
r = recvfrom(server, buf, sizeof(buf), 0, (struct sockaddr*)&remote, &len);
if (r > 0) {
buf[r] = 0;
printf("Recvive: %s\n", buf);
} else {
break;
}
}
close(server);
return 0;
}
client.c
#include
#include
#include
#include
#include
#include
#include
int main()
{
int sock = 0;
struct sockaddr_in addr = {0};
struct sockaddr_in remote = {0};
socklen_t len = 0;
char buf[128] = "D.T.Software";
int r = 0;
int brd = 1;
sock = socket(PF_INET, SOCK_DGRAM, 0);
if (sock == -1) {
printf("socket error\n");
return -1;
}
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(7777);
if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1) {
printf("udp bind error\n");
return -1;
}
remote.sin_family = AF_INET;
remote.sin_addr.s_addr = 0xFFFFFFFF;
// remote.sin_addr.s_addr = inet_addr("192.168.2.255");
remote.sin_port = htons(8888);
setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &brd, sizeof(brd));
while (1) {
len = sizeof(remote);
r = strlen(buf);
sendto(sock, buf, r, 0, (struct sockaddr*)&remote, len);
sleep(1);
}
close(sock);
return 0;
}
输出:
udp server start sucess
Recvive: D.T.Software
Recvive: D.T.Software
思考:UDP 是否还有其它一对多的数据发送方式?