广播的发送与接收

2022-09-17  本文已影响0人  二进制人类

广播的发送

流程

  1. 创建socket
  2. 设置套接字选项(在默认情况下,UDP套接字文件不允许发送广播,需要设置套接字文件为允许发送广播的模式;)
  3. 发送数据(将目的地址IP设置为广播地址,同时需要设置端口(接收主机通过端口号来接收,否则数据直接发送到UDP层就会丢失),调用sendto函数发送数据)

相关api

#include <sys/types.h>         
#include <sys/socket.h>

int getsockopt(int sockfd, int level, int optname, void *optval, socklen_t *optlen);    /* 获取套接字文件选项 */
int setsockopt(int sockfd, int level, int optname, const void *optval, socklen_t optlen);
/*
功能:设置套接字文件的选项
参数:
    参数1:sockfd表示的套接字文件的文件描述符;
    参数2:level表示的是协议的层序号
        SOL_SOCKET        通用套接字属性协议层
        IPPROTO_TCP       TCP协议层
        IPPROTO_IP        IP协议层
    参数3:optname表示的是对应协议层中的选项名称
        SO_BROADCAST    允许套接字发送广播
    参数4:optval表示选项的值,由于不同选项的参数不同,所以使用void *指针来实现。
    参数5:optlen表示参数4只想空间的大小。                                                                
返回值:    
    成功返回0,失败返回-1且修改errno的值。
    */

实例

#include <stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd;
    int optval;
    int ret;
    struct sockaddr_in broadcastaddr;
    char buf[128];

    /* 创建UDP数据报套接字文件 */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("socket");
        return -1;
    }

    /* 允许发送广播 */
    optval = 1;/* 1 = 允许, 0 = 不允许 */
    ret = setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &optval, sizeof(optval));
    if (ret == -1)
    {
        perror("setsockopt");
        return -1;
    }

    /* 发送广播数据 */
    /* 初始化广播地址空间结构体 */
    broadcastaddr.sin_family = AF_INET;
    broadcastaddr.sin_port = htons(8888);
    broadcastaddr.sin_addr.s_addr = inet_addr("192.168.0.255");

    while(1)
    {
        fgets(buf, sizeof(buf), stdin);
        /* 发送数据 */
        ret = sendto(sockfd, buf, sizeof(buf), 0, (const struct sockaddr *)&broadcastaddr, sizeof(broadcastaddr));
        if (ret == -1)
        {
            perror("sendto");
            return -1;
        }
    }
}

广播的接收

流程

  1. 创建socket
  2. 设置接收主机的IP地址和端口号(需要和发送广播的端口号保持一致)
  3. 接收广播数据

实例

#include <stdio.h>
#include <stdlib.h>

#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int main()
{
    int sockfd;
    int ret;
    struct sockaddr_in srvaddr;
    struct sockaddr_in cltaddr;
    socklen_t addrlen = sizeof(cltaddr);
    char buf[128];

    /* 创建UDP数据报套接字文件 */
    sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (sockfd == -1)
    {
        perror("socket");
        return -1;
    }

    /* 初始化服务器地址空间结构体 */
    srvaddr.sin_family = AF_INET;
    srvaddr.sin_port = htons(8888);
    srvaddr.sin_addr.s_addr = htonl(INADDR_ANY);
    /* 设置服务器的IP地址和端口号 */
    ret = bind(sockfd, (const struct sockaddr *)&srvaddr, sizeof(srvaddr));
    if (ret == -1)
    {
        perror("bind");
        return -1;
    }
    printf("init UDP server sucess\n");

    while(1)
    {
        /* 接收数据 */
        ret = recvfrom(sockfd, buf, sizeof(buf), 0, (struct sockaddr *)&cltaddr, &addrlen);
        if (ret == -1)
        {
            perror("recvfrom");
            return -1;
        }

        /* 解析得到对端的IP地址:端口 -> 数据 */
        printf("%s:%d -> buf : %s\n", inet_ntoa(cltaddr.sin_addr), ntohs(cltaddr.sin_port), buf);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读