【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;
}

原文地址:https://www.cnblogs.com/dplearning/p/4706062.html