广播方式主要是指使用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 LEN 256 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; }下面是简单的运行情况: