LINUX 网络编程 广播/组播通信

广播包

  • 只可以在同一个网段传播,不可以跨网段传播
  • 一个人广播 所有人都会接受到信息
  • 路由器是不会转发 广播数据包
  • 交换机可以转发 广播包
  • 广播包的 ARP地址是全F

目地MAC地址:FF:FF:FF:FF:FF:FF

本地MAC地址:10:c1:72:25:49:5e

对方就会知道本机的MAC地址 随之返回

ARP 协议

  • 局域网的MAX地址发现
  1. 只有两 呼应包

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 接口类型(章节)

setsockopt 接口类型(章节)

level指定控制套接字的层次

  1. SOL_SOCKET: 通用套接字选项
  2. IPPROTO_IP:IP选项
  3. 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
  1. 该选项用于将指定网络接口上的套接口加入IP 多播组,此套接口必须是AF_INET 地址族并且类型为SOCK_DGRAM
  2. struct ip_mreq {
  3. struct in_addr imr_multiaddr ;
  4. struct in_addr imr_interface;
  5. };
  6. ip_mreq.imr_multiaddr.s_addr 组播IP地址
  7. ip_mreq.in_interface.s_addr 接口的本地IP地址

IPPRO_TCP
TCP_MAXSEG TCP最大数据段的大小
TCP_NODELAY 不使用Nagle算法
  • send Breadcast
  1. #include <stdio.h>
  2. #include <sys/socket.h>
  3. #include <errno.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <arpa/inet.h>
  7. #include <unistd.h>
  8. int main(int argc, char* argv[])
  9. {
  10. int ser;
  11. /* 必须是数据报文形式传输*/
  12. ser = socket(AF_INET, SOCK_DGRAM,0);
  13. if (ser == -1) {
  14. perror("Socket Error !!");
  15. exit(1);
  16. }
  17. printf("Scoket OKEY !!\n");
  18. fflush(stdout);
  19. int _e = 1;
  20. int _f = setsockopt(ser, SOL_SOCKET, SO_BROADCAST, &_e, sizeof(_e));
  21. if (_f == -1) {
  22. perror("Sersockopt Error !!");
  23. exit(1);
  24. }
  25. struct sockaddr_in seraddr;
  26. seraddr.sin_family = AF_INET;
  27. seraddr.sin_port = htons(8888);
  28. seraddr.sin_addr.s_addr = inet_addr("192.168.1.255");
  29. //seraddr.sin_addr.s_addr = htonl(INADDR_ANY);
  30. int addr_len = sizeof(struct sockaddr);
  31. char buf[20];
  32. strcpy(buf, "hello message!");
  33. int len = sendto(ser, buf, sizeof(buf), 0,
  34. (struct sockaddr*)(&seraddr), addr_len);
  35. if (len < 0) {
  36. perror("sendto Error!!");
  37. exit(1);
  38. }
  39. printf("sendto or YES send /n");
  40. fflush(stdout);
  41. exit(0);
  42. }

组播包

源主机只发送一份数据 , 是属于该组的成员,都可以接收到一份原主机发送的数据的拷贝 ,以外的人接收不到

  • 组播包的IP段:224.0.0.1 ~ 239.255.255.255
  • 设置加入组

struct ip_mreq 结构体

  • imr_multiaddr :组 IP

  • imr_interface :接口的本地IP地址

主机进行解析域名

  1. 当主机拿到一个域名时 会先去 /etc/hosts 文件中去匹配有没有对应的IP地址 如果有就使用就不会往下走,没有就会到DNS上去寻找

  2. /etc/resolv.config 这个是DNS 服务器地址文件
    当没有在/etc/hosts文件中找到域名IP地址就会去/etc/resolv.config寻找DNS服务器的地址 在向DNS请求域名IP地址

gethostbyname 域名解析函数

  • 参数1: 域名
  • 返回值 :struct hostent
  1. struct hostent {
  2. const char *h_name; // 主机的官方名称
  3. char **h_aliases; // 主机备选名称
  4. short h_addrtype; // 主机返回地址类型
  5. short h_length; // 地址长度
  6. char **h_addr_list; // IP列表
  7. };