广播组播
广播
发送端:
第一步、创建套接字socket()
第二部、设置为允许发送广播权限setsockopt()
第三步、向广播地址发送数据sendto()
接收端:(必须绑定0地址或者广播地址)
第一步、创建套接字socket()
第二部、绑定本机地址和套接字 bind()
第三步、等待接受广播数据recvfrom()
广播实例:
发送者
//广播发送者代码实现
#include
#include
#include
#include
#include
#include //htons inet_addr
#include
#include
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr, "Usage: %s
exit(1);
}
int sockfd; //文件描述符
struct sockaddr_in broadcataddr; //服务器网络信息结构体
socklen_t addrlen = sizeof(broadcataddr);
//第一步:创建套接字
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(1);
}
//第二步:设置为允许发送广播权限
int on = 1;
if(setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on)) < 0)
{
perror("fail to setsockopt");
exit(1);
}
//第三步:填充广播信息结构体
broadcataddr.sin_family = AF_INET;
broadcataddr.sin_addr.s_addr = inet_addr(argv[1]); //192.168.3.255 255.255.255.255
broadcataddr.sin_port = htons(atoi(argv[2]));
//第四步:进行通信
char buf[128] = "";
while(1)
{
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = ' ';
if(sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&broadcataddr, addrlen) < 0)
{
perror("fail to sendto");
exit(1);
}
}
return 0;
}
接收者
//接收方代码实现
#include
#include
#include
#include
#include
#include //htons inet_addr
#include
#include
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr, "Usage: %s
exit(1);
}
int sockfd; //文件描述符
struct sockaddr_in broadcataddr;
socklen_t addrlen = sizeof(broadcataddr);
//第一步:创建套接字
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(1);
}
//第二步:填充广播信息结构体
broadcataddr.sin_family = AF_INET;
broadcataddr.sin_addr.s_addr = inet_addr(argv[1]); //192.168.3.255 255.255.255.255
broadcataddr.sin_port = htons(atoi(argv[2]));
//第三步:将套接字与广播信息结构体绑定
if(bind(sockfd, (struct sockaddr *)&broadcataddr, addrlen) < 0)
{
perror("fail to bind");
exit(1);
}
//第四步:进行通信
char text[32] = "";
struct sockaddr_in sendaddr;
while(1)
{
if(recvfrom(sockfd, text, sizeof(text), 0, (struct sockaddr *)&sendaddr, &addrlen) < 0)
{
perror("fail to recvfrom");
exit(1);
}
printf("[%s - %d]: %sn", inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), text);
}
return 0;
}
多播(又称组播)
多播概念:数据的收发只在同一分组中进行,所以多播又称组播
多播地址
ipv4的D类地址是多播地址
224.0.0.1~239.255.255.254
比起广播,多播具有可控性,只有加入多播组的接受者才能接受到信息
多播工作过程
多播编程流程:
发送者:
第一步:创建套接字 socket()
第二步:向多播地址发送数据 sendto()
接收者:
第一步:创建套接字 socket()
第二步:设置为加入多播组 setsockopt()
第三步:将套接字与多播信息结构体绑定 bind()
第五步:接收数据
多播地址结构体
setsockopt()
#include
2 int setsockopt(int socket, int level, int option_name,
3 const void *option_value, socklen_t option_len);
4 功能:设置一个套接字的选项(属性)
5 参数:
6 socket:文件描述符
7 level:协议层次
8 IPPROTO_IP IP层次
9 option_name:选项的名称
10 IP_ADD_MEMBERSHIP 加入多播组
11 option_value:设置的选项的值
12 struct ip_mreq
13 {
14 struct in_addr imr_multiaddr; //组播ip地址
15 struct in_addr imr_interface; //主机地址
16 INADDR_ANY 任意主机地址(自动获取你的主机地址)
17 };
18 option_len:option_value的长度
19 返回值:
20 成功:0
21 失败:‐1
多播实例
发送端:
#include
#include
#include
#include
#include
#include //htons inet_addr
#include
#include
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr, "Usage: %s
exit(1);
}
int sockfd; //文件描述符
struct sockaddr_in groupcastaddr; //服务器网络信息结构体
socklen_t addrlen = sizeof(groupcastaddr);
//第一步:创建套接字
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(1);
}
//第二步:填充组播信息结构体
groupcastaddr.sin_family = AF_INET;
groupcastaddr.sin_addr.s_addr = inet_addr(argv[1]); //224.x.x.x - 239.x.x.x
groupcastaddr.sin_port = htons(atoi(argv[2]));
//第三步:进行通信
char buf[128] = "";
while(1)
{
fgets(buf, sizeof(buf), stdin);
buf[strlen(buf) - 1] = ' '; //"hellon"-->"hello "
if(sendto(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&groupcastaddr, addrlen) < 0)
{
perror("fail to sendto");
exit(1);
}
}
return 0;
}
接收端:
#include
#include
#include
#include
#include
#include //htons inet_addr
#include
#include
int main(int argc, char const *argv[])
{
if(argc < 3)
{
fprintf(stderr, "Usage: %s
exit(1);
}
int sockfd; //文件描述符
struct sockaddr_in groupcastaddr;
socklen_t addrlen = sizeof(groupcastaddr);
//第一步:创建套接字
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("fail to socket");
exit(1);
}
//第二步:设置为加入多播组
struct ip_mreq mreq;
mreq.imr_multiaddr.s_addr = inet_addr(argv[1]);
mreq.imr_interface.s_addr = INADDR_ANY;
if(setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0)
{
perror("fail to setsockopt");
exit(1);
}
//第三步:填充组播信息结构体
groupcastaddr.sin_family = AF_INET;
groupcastaddr.sin_addr.s_addr = inet_addr(argv[1]); //224.x.x.x - 239.x.x.x
groupcastaddr.sin_port = htons(atoi(argv[2]));
//第四步:将套接字与广播信息结构体绑定
if(bind(sockfd, (struct sockaddr *)&groupcastaddr, addrlen) < 0)
{
perror("fail to bind");
exit(1);
}
//第五步:进行通信
char text[32] = "";
struct sockaddr_in sendaddr;
while(1)
{
if(recvfrom(sockfd, text, sizeof(text), 0, (struct sockaddr *)&sendaddr, &addrlen) < 0)
{
perror("fail to recvfrom");
exit(1);
}
printf("[%s - %d]: %sn", inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), text);
}
return 0;
}



