• 【linux高级程序设计】(第十五章)UDP网络编程应用 2


    UDP广播通信

    单播:一对一,TCP和UDP均可完成

    广播:只能UDP完成。广播时发送方只发送一个数据包,但是网络上的交换机默认转发广播数据包到所有端口。路由器默认不转发任何广播数据包。故广播在局域网范围内。

    组播:只有UDP可以完成。发送消息到同一个组播组的主机。视频电话、视频会议多采用。

    广播IP地址:主机号全1。网络号正常

    广播MAC地址:全1,即FF:FF:FF:FF:FF:FF

    广播数据帧格式

    处理过程:

    网卡驱动程序对比自己的MAC地址与目的MAC地址,发现是广播MAC地址,统一接收并交给OS(IP层)。

    IP层判断IP地址与自己是否一致。发现为IP地址为当前网段的广播地址,交给传输层

    传输层根据端口,如果有对应的端口交给应用程序处理。否则丢弃数据包。

    不管主机是否有进程接收广播消息,广播消息一定会被网卡收到并交个操作系统处理。会造成网络主机负担。

    设置socket可以发送广播消息

    int yes = 1;
    setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));

    接收端绑定地址信息时,需要制定接收任意地址信息的数据包。

    例子:

    发送端广播一段信息,接收端接收。

    注意:setsockopt为广播的目的应该是告知MAC地址为FF:FF:FF:FF:FF:FF 而广播的IP地址需要我们自己写上。即(网络号:全1主机号)。通过ifconfig获取。

    发送端

    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<netinet/tcp.h>
    #include<sys/socket.h>
    #include<sys/wait.h>
    #include<unistd.h>
    #include<arpa/inet.h>
    #include<sys/time.h>
    
    int main(int argc, char **argv)
    {
        struct sockaddr_in s_addr;
        int sock;
        int addr_len;
        int len;
        char buff[128];
        int yes;
        //UDP 创建socket
        if((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("create socket.
    
    ");
        }
        //设置socket为可发送广播消息
        yes = 1;
        setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &yes, sizeof(yes));
        
        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(7838);
        if(argv[1])
        {
            s_addr.sin_addr.s_addr = inet_addr(argv[1]); //参数1 广播地址
        }    
        else
        {
            printf("input sever ip!
    ");
            exit(0);
        }
        addr_len = sizeof(s_addr);
        strcpy(buff, "hello message");
        //发送消息
        len = sendto(sock, buff, strlen(buff), 0, (struct sockaddr *)&s_addr, addr_len);
        if(len < 0)
        {
            printf("
    
    send error.
    
    ");
            exit(EXIT_FAILURE);
        }
        printf("send success.
    
    ");
        return 0;
    }

    接收端

    #include<stdio.h>
    #include<stdlib.h>
    #include<errno.h>
    #include<string.h>
    #include<sys/types.h>
    #include<netinet/in.h>
    #include<netinet/tcp.h>
    #include<sys/socket.h>
    #include<sys/wait.h>
    #include<unistd.h>
    #include<arpa/inet.h>
    #include<sys/time.h>
    
    int main(int argc, char **argv)
    {
        struct sockaddr_in s_addr;
        struct sockaddr_in c_addr;
        int sock;
        socklen_t addr_len;
        int len;
        char buff[128];
        //创建socket UDP
        if((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1)
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("create socket.
    
    ");
        }
        memset(&s_addr, 0, sizeof(struct sockaddr_in));
        
        s_addr.sin_family = AF_INET;
        s_addr.sin_port = htons(7838);
        s_addr.sin_addr.s_addr = INADDR_ANY;
        //绑定IP地址
        if((bind(sock, (struct sockaddr *)&s_addr, sizeof(s_addr))) == -1)
        {
            perror("bind");
            exit(EXIT_FAILURE);
        }
        else
        {
            printf("bind address to socket.
    
    ");
        }
        addr_len = sizeof(c_addr);
        while(1)
        {
            //阻塞方式接收数据
            len = recvfrom(sock, buff, sizeof(buff) - 1, 0, (struct sockaddr *)&c_addr, &addr_len);
            if(len < 0)
            {
                perror("recvfrom");
                exit(EXIT_FAILURE);
            }
            buff[len] = '';
            printf("recive come from %s:%d message:%s
    
    ", inet_ntoa(c_addr.sin_addr), ntohs(c_addr.sin_port), buff);
        }
        return 0;
    }

  • 相关阅读:
    24张图,九大数据结构安排得明明白白
    mysql中的mvcc解读
    常见电商项目的数据库表设计(MySQL版)
    两万字深度介绍分布式系统原理,一文入魂
    使用消息中间件时,如何保证消息仅仅被消费一次?
    GCC/G++选项 -Wl,-Bstatic和-Wl,-Bdynamic
    sql 练习
    设计模式-单例模式
    设计模式-抽象工厂模式
    设计模式-工厂方法模式
  • 原文地址:https://www.cnblogs.com/dplearning/p/4706062.html
Copyright © 2020-2023  润新知