广播方式主要是指使用UDP套接口发送数据,发送数据的目标地址不是普通的地址,而是所指定网络的广播地址。
什么是广播地址?是指IP地址中主机地址部分全为1的IP地址。
下面是一个广播发送简单流程图。
如何实现广播发送?
一般情况下使用sendto函数只能向非广播地址发送数据,如果要发送广播数据就必须要告诉内核,可以通过设置套接字属性为SO_BROADCAST来坐到这一点。
int on = 1;
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
广播的缺点:
不管主机有没有程序在接收或者处理广播信息,广播信息一定会被网卡收到并提交给操作系统处理,所以会造成网络上数据流量增大,对不接收广播信息的主机造成一定的负担。
下面是一个简单的发送广播的程序。
服务端每隔3s发送一个广播信息,信息为系统当前的时间。
服务器端代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define LEN256
void getTime(char *curTime)
{
time_t tm;
time(&tm);
snprintf(curTime, LEN, "%s\n", ctime(&tm));
}
int main(int argc, char **argv)
{
struct sockaddr_in peeraddr;
int sockfd = 0;
int on = 1;
int num = 0;
char msg[LEN] = {0};
if (argc != 3)
{
printf("Usage:%s<IP address> <PORT>\n", argv[0]);
return -1;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
printf("Create socket fails!\n");
return -1;
}
//设置套接字为广播模式 SO_BROADCAST
setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
bzero(&peeraddr, sizeof(peeraddr));
peeraddr.sin_family = AF_INET;
if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0)
{
printf("IP address is error!\n");
return -1;
}
peeraddr.sin_port = htons(atoi(argv[2]));
for (;;)
{
getTime(msg);
num = sendto(sockfd, msg, strlen(msg), 0, (struct sockaddr *)&peeraddr, sizeof(struct sockaddr_in));
fflush(stdout);
sleep(3);
}
close(sockfd);
return 1;
}
客户端程序:
#include <stdio.h>下面是简单的运行情况:
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/socket.h>
#include <time.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define LEN 256
int main(int argc, char **argv)
{
struct sockaddr_in localaddr;
int sockfd = 0;
int num = 0;
char msg[LEN] = {0};
if (argc != 2)
{
printf("Usage: %s<PORT>\n", argv[0]);
return -1;
}
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0)
{
printf("Create socket fails!\n");
return -1;
}
bzero(&localaddr, sizeof(localaddr));
localaddr.sin_family = AF_INET;
localaddr.sin_port = htons(atoi(argv[1]));
localaddr.sin_addr.s_addr = htonl(INADDR_ANY);
int opt = SO_REUSEADDR;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
if (bind(sockfd, (struct sockaddr *)&localaddr, sizeof(struct sockaddr_in)) < 0)
{
printf("bind fails!\n");
return -1;
}
num = read(sockfd, msg, LEN);
if (num <= 0)
{
printf("read message fails!\n");
return -1;
}
msg[num] = '\0';
printf("time:%s\n", msg);
close(sockfd);
return 1;
}