LINUX 网络编程 广播/组播通信
广播包
- 只可以在同一个网段传播,不可以跨网段传播
- 一个人广播 所有人都会接受到信息
- 路由器是不会转发 广播数据包
- 交换机可以转发 广播包
- 广播包的 ARP地址是全F
目地MAC地址:FF:FF:FF:FF:FF:FF
本地MAC地址:10:c1:72:25:49:5e
对方就会知道本机的MAC地址 随之返回
ARP 协议
- 局域网的MAX地址发现
- 只有两 呼应包
VLAN
- 隔离池 阻断同一个局域网的ARP通信
- 属于逻辑隔离
广播 编程
- 广播 socket必须是 帧传输SOCK_DGRAM
setsockopt() 设置选择值
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
头文件 :#include
sock:将要被设置套接字
level:套接字接口类型(章节)
optname:设置的章中的哪一个节
optval: 指向包含新选项值的缓冲
optlen:缓冲 长度
返回值:成功为0
失败 -1
getsockopt()获取选择值
int setsockopt(int sock, int level, int optname, const void *optval, socklen_t optlen);
setsockopt 接口类型(章节)
level指定控制套接字的层次
- SOL_SOCKET: 通用套接字选项
- IPPROTO_IP:IP选项
- IPPROTO_TCP: TCP选项
optname 章节中的哪一个节
SOL_SOCKET 中的选项
参数 | 含义 | 类型 |
---|---|---|
SO_BROADCAST | 允许发送广播数据 | int |
SO_DEBUG | 允许调试 | int |
0 | 禁止发送广播 | int |
1 | 允许发送广播 | int |
SO_LINGER | 延迟关闭连接 | struct linger |
SO_RCVTIMEO | 接收超时 | struct linger |
SO_SNDTIMEO | 发送超时 | struct linger |
SO_TYPE | 获得套接字类型 | int |
SO_REUSEADDR | 允许套接口和一个已在使用中的地址捆绑 | bool |
SO_RCVBUF | 接收缓冲区大小 | int |
IPPROTO_IP
参数 | 含义 | 类型 |
---|---|---|
IP_HDRINCL | 自定义数据包 | int |
IP_OPTINOS | IP首部选项 | int |
IP_TOS | 服务类型 | int |
IP_TTL | 生存时间 | int |
IP_ADD_MEMBERSHIP | 用于加入多播组 | struct ip_mreq |
IP_DROP_MEMBERSHIP | 用于退出多播组 | struct ip_mreq |
- IP_ADD_MEMBERSHIP / IP_DROP_MEMBERSHIP
该选项用于将指定网络接口上的套接口加入IP 多播组,此套接口必须是AF_INET 地址族并且类型为SOCK_DGRAM
struct ip_mreq {
struct in_addr imr_multiaddr ;
struct in_addr imr_interface;
};
ip_mreq.imr_multiaddr.s_addr 组播IP地址
ip_mreq.in_interface.s_addr 接口的本地IP地址
IPPRO_TCP
TCP_MAXSEG | TCP最大数据段的大小 |
---|---|
TCP_NODELAY | 不使用Nagle算法 |
- send Breadcast
#include <stdio.h>
#include <sys/socket.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
int ser;
/* 必须是数据报文形式传输*/
ser = socket(AF_INET, SOCK_DGRAM,0);
if (ser == -1) {
perror("Socket Error !!");
exit(1);
}
printf("Scoket OKEY !!\n");
fflush(stdout);
int _e = 1;
int _f = setsockopt(ser, SOL_SOCKET, SO_BROADCAST, &_e, sizeof(_e));
if (_f == -1) {
perror("Sersockopt Error !!");
exit(1);
}
struct sockaddr_in seraddr;
seraddr.sin_family = AF_INET;
seraddr.sin_port = htons(8888);
seraddr.sin_addr.s_addr = inet_addr("192.168.1.255");
//seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
int addr_len = sizeof(struct sockaddr);
char buf[20];
strcpy(buf, "hello message!");
int len = sendto(ser, buf, sizeof(buf), 0,
(struct sockaddr*)(&seraddr), addr_len);
if (len < 0) {
perror("sendto Error!!");
exit(1);
}
printf("sendto or YES send /n");
fflush(stdout);
exit(0);
}
组播包
源主机只发送一份数据 , 是属于该组的成员,都可以接收到一份原主机发送的数据的拷贝 ,以外的人接收不到
- 组播包的IP段:224.0.0.1 ~ 239.255.255.255
- 设置加入组
struct ip_mreq 结构体
imr_multiaddr :组 IP
imr_interface :接口的本地IP地址
主机进行解析域名
当主机拿到一个域名时 会先去 /etc/hosts 文件中去匹配有没有对应的IP地址 如果有就使用就不会往下走,没有就会到DNS上去寻找
/etc/resolv.config 这个是DNS 服务器地址文件
当没有在/etc/hosts文件中找到域名IP地址就会去/etc/resolv.config寻找DNS服务器的地址 在向DNS请求域名IP地址
gethostbyname 域名解析函数
- 参数1: 域名
- 返回值 :struct hostent
struct hostent {
const char *h_name; // 主机的官方名称
char **h_aliases; // 主机备选名称
short h_addrtype; // 主机返回地址类型
short h_length; // 地址长度
char **h_addr_list; // IP列表
};