广播和组播
一。广播
服务端向192.168.1.1~192.168.1.254的所有IP的9000端口发送数据
服务端
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <stdlib.h> 4 #include <sys/socket.h> 5 #include <string.h> 6 #include <arpa/inet.h> 7 #include <net/if.h> 8 9 #define SERVER_PORT 8000 //服务器端口 10 #define MAXLINE 1500 11 12 #define BROADCAST_IP "192.168.1.255" //广播地址 13 #define CLIENT_PORT 9000 //广播的端口 14 15 int main(void) 16 { 17 int sockfd; 18 struct sockaddr_in serveraddr, clientaddr; 19 char buf[MAXLINE]; 20 21 /* 构造用于UDP通信的套接字 */ 22 sockfd = socket(AF_INET, SOCK_DGRAM, 0); 23 24 bzero(&serveraddr, sizeof(serveraddr)); 25 serveraddr.sin_family = AF_INET; /* IPv4 */ 26 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /* 本地任意IP INADDR_ANY = 0 */ 27 serveraddr.sin_port = htons(SERVER_PORT); 28 29 bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); 30 31 int flag = 1; 32 setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &flag, sizeof(flag)); //设置套接字打开广播权限 33 34 /*构造 client 地址 IP+端口 192.168.1.255+9000 */ 35 bzero(&clientaddr, sizeof(clientaddr)); 36 clientaddr.sin_family = AF_INET; 37 inet_pton(AF_INET, BROADCAST_IP, &clientaddr.sin_addr.s_addr); 38 clientaddr.sin_port = htons(CLIENT_PORT); 39 40 int i = 0; 41 while (1) { 42 sprintf(buf, "this is the %d datagram\n", i++); 43 //fgets(buf, sizeof(buf), stdin); 44 sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr));//发送数据 45 sleep(1); 46 } 47 close(sockfd); 48 return 0; 49 }
客户端
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <string.h> 4 #include <sys/socket.h> 5 #include <arpa/inet.h> 6 7 #define SERVER_PORT 8000 8 #define MAXLINE 4096 9 #define CLIENT_PORT 9000 10 11 int main(int argc, char *argv[]) 12 { 13 struct sockaddr_in localaddr; 14 int confd; 15 ssize_t len; 16 char buf[MAXLINE]; 17 18 //1.创建一个socket 19 confd = socket(AF_INET, SOCK_DGRAM, 0); 20 21 //2.初始化本地端地址 22 bzero(&localaddr, sizeof(localaddr)); 23 localaddr.sin_family = AF_INET; 24 inet_pton(AF_INET, "0.0.0.0" , &localaddr.sin_addr.s_addr); 25 localaddr.sin_port = htons(CLIENT_PORT); 26 27 int ret = bind(confd, (struct sockaddr *)&localaddr, sizeof(localaddr)); //显式绑定不能省略 28 if (ret == 0) 29 printf("...bind ok...\n"); 30 31 while (1) { 32 len = recvfrom(confd, buf, sizeof(buf), 0, NULL, 0); //接收数据 33 write(STDOUT_FILENO, buf, len); 34 } 35 close(confd); 36 37 return 0; 38 }
二。组播
服务端向所有加入239.0.0.2多播组的所有IP的9000端口发送数据
服务端
1 #include <stdio.h> 2 #include <unistd.h> 3 #include <string.h> 4 #include <arpa/inet.h> 5 #include <net/if.h> 6 7 #define SERVER_PORT 8000 8 #define CLIENT_PORT 9000 9 #define MAXLINE 1500 10 11 #define GROUP "239.0.0.2" 12 13 int main(void) 14 { 15 int sockfd; 16 struct sockaddr_in serveraddr, clientaddr; 17 char buf[MAXLINE]; 18 struct ip_mreqn group; 19 20 /* 21 struct ip_mreqn { 22 struct in_addr imr_multiaddr; /* IP multicast address of group */ 23 struct in_addr imr_address; /* local IP address of interface */ 24 int imr_ifindex; /* Interface index */ 25 };*/ 26 27 sockfd = socket(AF_INET, SOCK_DGRAM, 0); /* 构造用于UDP通信的套接字 */ 28 29 bzero(&serveraddr, sizeof(serveraddr)); 30 serveraddr.sin_family = AF_INET; /* IPv4 */ 31 serveraddr.sin_addr.s_addr = htonl(INADDR_ANY); /* 本地任意IP INADDR_ANY = 0 */ 32 serveraddr.sin_port = htons(SERVER_PORT); 33 34 bind(sockfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)); 35 36 inet_pton(AF_INET, GROUP, &group.imr_multiaddr); /* 设置组地址 */ 37 inet_pton(AF_INET, "0.0.0.0", &group.imr_address); /* 本地任意IP */ 38 group.imr_ifindex = if_nametoindex("eth0"); /* 给出网卡名,转换为对应编号: eth0 --> 编号 命令:ip ad */ 39 40 setsockopt(sockfd, IPPROTO_IP, IP_MULTICAST_IF, &group, sizeof(group)); /* 组播权限 */ 41 42 bzero(&clientaddr, sizeof(clientaddr)); /* 构造 client 地址 IP+端口 */ 43 clientaddr.sin_family = AF_INET; 44 inet_pton(AF_INET, GROUP, &clientaddr.sin_addr.s_addr); /* IPv4 239.0.0.2+9000 */ 45 clientaddr.sin_port = htons(CLIENT_PORT); 46 47 int i = 0; 48 while (1) { 49 sprintf(buf, "this is the %d datagram\n", i++); 50 //fgets(buf, sizeof(buf), stdin); 51 sendto(sockfd, buf, strlen(buf), 0, (struct sockaddr *)&clientaddr, sizeof(clientaddr)); //向多播组9000端口发送数据 52 sleep(1); 53 } 54 55 close(sockfd); 56 57 return 0; 58 }
客户端
#include <stdio.h> #include <unistd.h> #include <string.h> #include <arpa/inet.h> #include <net/if.h> #define SERVER_PORT 8000 #define CLIENT_PORT 9000 #define GROUP "239.0.0.2" //组播地址 int main(int argc, char *argv[]) { struct sockaddr_in localaddr; int confd; ssize_t len; char buf[BUFSIZ]; struct ip_mreqn group; /* 组播结构体 */ confd = socket(AF_INET, SOCK_DGRAM, 0); bzero(&localaddr, sizeof(localaddr)); /* 初始化 */ localaddr.sin_family = AF_INET; inet_pton(AF_INET, "0.0.0.0" , &localaddr.sin_addr.s_addr); localaddr.sin_port = htons(CLIENT_PORT); bind(confd, (struct sockaddr *)&localaddr, sizeof(localaddr)); inet_pton(AF_INET, GROUP, &group.imr_multiaddr); /* 设置组地址 */ inet_pton(AF_INET, "0.0.0.0", &group.imr_address); /* 使用本地任意IP添加到组播组 */ group.imr_ifindex = if_nametoindex("eth0"); /* 通过网卡名-->编号 ip ad */ setsockopt(confd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &group, sizeof(group));/* 设置client 加入多播组 */ while (1) { len = recvfrom(confd, buf, sizeof(buf), 0, NULL, 0); //接收数据 write(STDOUT_FILENO, buf, len); } close(confd); return 0; }