二、广播
1、广播特点
多点通讯 全网广播:255.255.255.255 容易造成网络风暴 子网广播:x.x.x.255 只允许数据报套接字操作 /*设置网络允许广播*/ int val = 1 setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(int));
2、广播发送端流程
创建数据报(udp)套接字
设置套接字属性允许广播
设置接收方IP为广播地址
设置广播端口号
发送数据
3、广播发送示例
/*========================================================
* > 文 件 名 称: send.c
* > 创 建 者: 清风徐来
* > 邮 箱: zhangsl_cd@hqyj.com
* > 创 建 时 间: 2020年08月24日 星期一 09时19分43秒
==========================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/ip.h>
#define N 64
#define PORT 8888
int main()
{
int fd, val = 1;
if(-1 == (fd = socket(AF_INET, SOCK_DGRAM, 0))){
perror("socket");
exit(-1);
}
/*设置允许广播*/
if(-1 == setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &val, sizeof(int))){
perror("setsockopt");
exit(-1);
}
/*设置接收方的IP和PORT*/
struct sockaddr_in sddr, cddr;
sddr.sin_family = AF_INET;
sddr.sin_port = htons(PORT);
sddr.sin_addr.s_addr = inet_addr("192.168.10.255");
char buf[N] = {0};
int len = sizeof cddr;
while(1){
printf("send> ");fflush(stdout);
fgets(buf, N, stdin);
if(-1 == sendto(fd, buf, N-1, 0, (void *)&sddr, sizeof(sddr))){
perror("sendto");
exit(-1);
}
if(0 == strncasecmp(buf, "quit", 4)){
break;
}
bzero(buf, N);
if(-1 == recvfrom(fd, buf, N, 0, (void *)&cddr, &len)){
perror("recvfrom");
exit(-1);
}
printf("recv> %s\n", buf);
}
close(fd);
}
三、组播(多播)
1、组播(多播)特点
属于多点通讯。
单播是一对一,广播是发送给所有主机,带宽占用大容易出现网络风暴,而多播是折中处理,只有加入多播组才能接收多播数据 组播IP:224.0.0.0 - 239.255.255.255 属于D类地址
组播通信需要先创建多播组(发送方和接收方任意一方创建即可)
创建/加入多播组,设置网络属性 创建:IP_MULTICAST_IF struct ip_mreqn { struct in_addr imr_multiaddr; /* IP多点传送组地址 */ struct in_addr imr_address; /* 本地接口的IP地址 */ int imr_ifindex; /* 接口索引 */ //即网卡编号 }; imr_ifindex: #include <net/if.h> unsigned if_nametoindex(const char *ifname); //自动获取指定设备的索引号 加入:IP_ADD_MEMBERSHIP struct ip_mreqn { struct in_addr imr_multiaddr; /* IP多点传送组地址 */ struct in_addr imr_address; /* 本地接口的IP地址 */ int imr_ifindex; /* 接口索引 */ }; imr_ifindex: #include <net/if.h> unsigned if_nametoindex(const char *ifname); //自动获取指定设备的索引号
2、组播发送方流程
创建数据报套接字(udp)
接收方地址定为组播地址
设置端口号
发送数据
3、组播发送方示例
/*========================================================
* > 文 件 名 称: send.c
* > 创 建 者: 清风徐来
* > 邮 箱: zhangsl_cd@hqyj.com
* > 创 建 时 间: 2020年08月24日 星期一 10时35分12秒
==========================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/ip.h>
#include <net/if.h>
#define N 64
#define RPORT 8888
int main()
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == fd){
perror("socket");
exit(-1);
}
/*填充ip_mreqn结构体*/
struct ip_mreqn mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.3.3.3");
mreq.imr_address.s_addr = inet_addr("0.0.0.0"); //
mreq.imr_ifindex = if_nametoindex("eth0");
/*创建多播组*/
if(-1 == setsockopt(fd, IPPROTO_IP, IP_MULTICAST_IF, &mreq, sizeof(mreq))){
perror("setsockopt");
exit(-1);
}
/*填充发送接收方IP和PORT*/
struct sockaddr_in sddr;
sddr.sin_family = AF_INET;
sddr.sin_port = htons(RPORT); //RPORT is define :8888
sddr.sin_addr.s_addr = inet_addr("224.3.3.3"); //向多播组发送
char buf[N] = {0};
while(1){
printf("send> ");fflush(stdout);
fgets(buf, N, stdin);
if(-1 == sendto(fd, buf, N, 0, (void *)&sddr, sizeof(sddr))){
perror("sendto");
exit(-1);
}
if(!strncasecmp(buf, "quit", 4)){
break;
}
}
}
4、组播接收方流程
创建数据报套接字(udp)
加入多播组
绑定IP地址(加入组的组IP或"0.0.0.0")和端口号
等待接收数据
5、组播接收方示例
/*========================================================
* > 文 件 名 称: send.c
* > 创 建 者: 清风徐来
* > 邮 箱: zhangsl_cd@hqyj.com
* > 创 建 时 间: 2020年08月24日 星期一 10时35分12秒
==========================================================*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
#include <netinet/ip.h>
#include <net/if.h>
#define N 64
#define RPORT 8888
int main()
{
int fd = socket(AF_INET, SOCK_DGRAM, 0);
if(-1 == fd){
perror("socket");
exit(-1);
}
/*填充ip_mreqn结构体*/
struct ip_mreqn mreq;
mreq.imr_multiaddr.s_addr = inet_addr("224.1.3.3");
mreq.imr_address.s_addr = inet_addr("0.0.0.0"); //
mreq.imr_ifindex = if_nametoindex("eth0");
/*加入多播组*/
if(-1 == setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))){
perror("setsockopt");
exit(-1);
}
/*填充发送接收方IP和PORT*/
struct sockaddr_in sddr, cin;
sddr.sin_family = AF_INET;
sddr.sin_port = htons(RPORT); //RPORT is define :8888
sddr.sin_addr.s_addr = inet_addr("0.0.0.0");
/*绑定自己的IP和PORT*/
if(-1 == bind(fd, (void *)&sddr, sizeof(sddr))){
perror("bind");
exit(-1);
}
int len = sizeof cin;
char buf[N] = {0};
while(1){
if(-1 == recvfrom(fd, buf, N, 0, (void *)&cin, &len)){
perror("sendto");
exit(-1);
}
if(!strncasecmp(buf, "quit", 4)){
break;
}
printf("recv> %s", buf);
}
}