UDP 广播

一、UDP 通信图解

UDP 广播_第1张图片

UDP通信、本地套接字_呵呵哒( ̄▽ ̄)"的博客-CSDN博客https://blog.csdn.net/weixin_41987016/article/details/132523536?spm=1001.2014.3001.5501

#include 
#include 
ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
	- 参数:
		- sockfd : 通信的fd
		- buf : 要发送的数据
		- len : 发送数据的长度
		- flags : 0
		- dest_addr : 通信的另外一端的地址信息
		- addrlen : 地址的内存大小
	
ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
	- 参数:
		- sockfd : 通信的fd
		- buf : 接收数据的数组
		- len : 数组的大小
 
		- flags : 0
		- src_addr : 用来保存另外一端的地址信息,不需要可以指定为NULL
		- addrlen : 地址的内存大小

二、广播

广播:向子网中多态计算机发送消息,并且子网中所有计算机都可以接收到发送方发送的消息,每个广播消息都包含一个特殊的IP地址,这个IP中子网内主机标志部分的二进制全部为1

         a.只能在局域网中使用

         b.客户端需要绑定服务器广播使用的端口,才可以接收到广播信息

UDP 广播_第2张图片

// 设置广播属性的函数
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
    - sockfd : 文件描述符
    - level : SOL_SOCKET
    - optname : SO_BROADCAST
    - optval : int类型的值,为1表示允许广播
    - optlen : optval的大小

UDP 广播_第3张图片

UDP 广播_第4张图片

UDP 广播_第5张图片

什么是广播?

  • ① 数据包发送方式只有一个接受方,称为单播
  • ② 如果同时发给局域网中的所有主机,称为广播
  • ③ 只有用户数据报(使用UDP协议)套接字才能广播

广播地址

  • ① 一个网络内主机号全为1的IP地址为广播地址
  • ② 发到该地址的数据包被所有的主机接收
  • ③ 255.255.255.255在所有网段中都代表广播地址

 ​UDP 广播_第6张图片

>>实验一

bro_server.c

#include 
#include 
#include 
#include 
#include 

int main () {
    // 1.创建一个通信的socket
    int fd = socket(PF_INET, SOCK_DGRAM, 0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }

    // 2.设置广播属性
    int op = 1;
    setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &op, sizeof(op));

    // 3.创建一个广播的地址
    struct sockaddr_in broaddr;
    broaddr.sin_family = AF_INET;
    broaddr.sin_port = htons(9999);
    // broaddr.sin_addr.s_addr = inet_addr("192.168.90.255");
    inet_pton(AF_INET,"192.168.90.255",&broaddr.sin_addr.s_addr);//设置广播地址,必须为本机/虚拟机的广播地址才行

    // 3.通信
    int num = 0;
    while (1) {
        char sendBuf[128];
        sprintf(sendBuf,"hello,client....%d\n",num++);
        // 发送数据
        sendto(fd,sendBuf,strlen(sendBuf) + 1,0,(struct sockaddr*)&broaddr,sizeof(broaddr));
        printf("广播的数据:%s\n",sendBuf);
        sleep(1);
    }
    close(fd);
    return 0;
}

bro_client.c

#include 
#include 
#include 
#include 
#include 

int main () {
    // 1.创建一个通信的socket
    int fd = socket(PF_INET,SOCK_DGRAM,0);
    if(fd == -1) {
        perror("socket");
        exit(-1);
    }

    // 2.客户端绑定本地的IP和端口
    struct sockaddr_in addr;
    addr.sin_family = AF_INET;
    addr.sin_port = htons(9999);
    addr.sin_addr.s_addr = INADDR_ANY;

    int ret = bind(fd,(struct sockaddr *)&addr,sizeof(addr));
    if(ret == -1) {
        perror("bind");
        exit(-1);
    }

    // 3.通信
    while(1) {
        char buf[128];
        // 接收数据
        int num = recvfrom(fd,buf,sizeof(buf),0,NULL,NULL);
        printf("server say: %s\n",buf);
    }

    close(fd);
    return 0;
}

UDP 广播_第7张图片

UDP 广播_第8张图片UDP 广播_第9张图片

 >>实验二

① 安装wireshark:sudo apt install wireshark

② ifconfig 查看广播地址

UDP 广播_第10张图片

③ 运行wireshark,输入host 192.168.90.255

UDP 广播_第11张图片

④ 打开另一台虚拟机,IP地址为:192.168.90.132

⑤ 执行以下命令

⑥ 在第一个终端输入

 UDP 广播_第12张图片

 UDP 广播_第13张图片

 UDP 广播_第14张图片

UDP 广播_第15张图片

sender.c

#include 
#include 
#include 
#include  /* superser of previos */
#include 
#include 
#include 
#include 

#define ErrExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;

int main(int argc, char *argv[]) {
    int fd = -1;
    Addr_in peeraddr;
    socklen_t peerlen = sizeof(peeraddr);
    char buf[BUFSIZ] = {};
    /* 参数检查 */
    if(argc < 3) {
        fprintf(stderr, "Usage: %s  \n", argv[0]);
        exit(EXIT_FAILURE);
    }
    /* 创建套接字 */
    if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) 
        ErrExit("socket");
    
    /* 允许广播 */
    int on = 1;
    setsockopt(fd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));


    /* 设置通信结构体 */
    peeraddr.sin_family = AF_INET;
    peeraddr.sin_port = htons(atoi(argv[2]));
    if(!inet_aton(argv[1], &peeraddr.sin_addr)) {
        fprintf(stderr, "Invalid IP address\n");
        exit(EXIT_FAILURE);
    }

    while(1) {
        fgets(buf,BUFSIZ,stdin);
        sendto(fd, buf, strlen(buf)+1, 0, (Addr*)&peeraddr, peerlen);
    }

    return 0;
}

receiver.c

#include 
#include 
#include 
#include  /* superser of previos */
#include 
#include 
#include 
#include 

#define ErrExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)
typedef struct sockaddr Addr;
typedef struct sockaddr_in Addr_in;

int main(int argc, char *argv[]) {

    int fd = -1;
    Addr_in myaddr,peeraddr;
    socklen_t peerlen = sizeof(peeraddr);
    char buf[BUFSIZ] = {};
    /* 参数检查 */
    if(argc < 3) {
        fprintf(stderr, "Usage: %s  \n", argv[0]);
        exit(EXIT_FAILURE);
    }
    /* 创建套接字 */
    if((fd = socket(AF_INET,SOCK_DGRAM,0)) < 0) 
        ErrExit("socket");

    /* 设置通信结构体 */
    myaddr.sin_family = AF_INET;
    myaddr.sin_port = htons(atoi(argv[2]));
    if(!inet_aton(argv[1], &myaddr.sin_addr)) {
        fprintf(stderr, "Invalid address\n");
        exit(EXIT_FAILURE);
    }
        
    /* 绑定通信结构体 */
    if(bind(fd, (Addr*)&myaddr, sizeof(myaddr)) < 0)
        ErrExit("bind");
    while (1) {
        recvfrom(fd, buf, BUFSIZ, 0, (Addr*)&peeraddr, &peerlen);
        printf("[%s:%d]%s\n",inet_ntoa(peeraddr.sin_addr),ntohs(peeraddr.sin_port),buf);
    }
    return 0;
}

你可能感兴趣的:(udp,网络协议,网络,广播)