【问题标题】:Can't read RTP packet (or get its size) from multicast socket via several 'read' calls无法通过多个“读取”调用从多播套接字读取 RTP 数据包(或获取其大小)
【发布时间】:2020-01-21 12:15:04
【问题描述】:

我无法从使用打开的多播套接字读取 RTP 数据包 以下函数:

int
    open_multicast_socket
        (const char *group_address,
         uint16_t port)
{
    assert(group_address != NULL);

    int
        s;

    if (-1 != (s = socket(
        AF_INET, SOCK_DGRAM, 0
    )))
    {
        int
            reuse = 1;

        if (-1 != setsockopt(
            s, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof reuse
        ))
        {
            struct sockaddr_in
                sock_addr;

            bzero(&sock_addr, sizeof sock_addr);

            if (1 == inet_pton(
                AF_INET, group_address, &sock_addr.sin_addr
            ))
            {
                sock_addr.sin_family      = AF_INET;
                sock_addr.sin_port        = htons(port);

                if (0 == bind(
                    s, (struct sockaddr*)&sock_addr, sizeof sock_addr
                ))
                {
                    struct ip_mreq
                        mreq = {
                            .imr_multiaddr.s_addr = inet_addr(group_address),
                            .imr_interface.s_addr = htonl(INADDR_ANY)
                        };

                    if (0 == setsockopt(
                        s, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof mreq
                    ))
                    {
                        //fcntl(s, F_SETFL, O_NONBLOCK);
                        return s;
                    } // setsockopt
                    else
                    {
                        perror("setsockopt");
                        close(s);
                    }
                } // bind
                else
                {
                    perror("bind");
                    close(s);
                }
            } // inet_pton
            else
            {
                perror("inet_pton");
                close(s);
            }
        } // setsockopt
        else
        {
            perror("setsockopt");
            close(s);
        }
    } // socket
    else
    {
        perror("socket");
    }

    return -1;
}

如果我在一个 read 操作中读取 RTP 标头和有效负载,我会得到整个 包。但是,如果我尝试先接收 RTP 标头,那么 - 自定义 有效载荷中的标头 - 第二个 read 总是获得下一个 RTP 标头, 丢弃所有附加数据。因为有效载荷长度可能会有所不同,所以唯一的方法是 接收一个完整的数据包,似乎是猜测它的最大可能大小。

我尝试在阅读之前获取一些可用字节:

ioctl(sock, FIONREAD, &nbytes);

但它总是返回 0。

对套接字的轮询总是失败,就好像根本没有数据可用。

启用非阻塞时(即fcntl(sock, F_SETFL, O_NONBLOCK);) - read 总是失败 (-1),recv(sock, buf, buf_len, MSG_DONTWAIT) 也是。

那么有没有办法通过相应的非阻塞来正确解析 RTP 数据包 read 来电?

非阻塞是必不可少的,因为应该可以检查连接是否丢失并在必要时重新打开套接字。

【问题讨论】:

    标签: c sockets rtp multicastsocket


    【解决方案1】:

    与基于流的协议 TCP 不同,UDP 是基于数据包的协议。这意味着无论何时从 UDP 套接字(无论是否多播)读取数据,您都会得到一个 UDP 数据报。如果您的缓冲区不够大,无法容纳整个数据报,那么剩余的数据就会丢失。

    确保您的缓冲区足够大以容纳完整的数据报。如果您的网络支持端到端巨型帧,则意味着您的缓冲区应为 9000 字节,否则应为 1500 字节。

    【讨论】:

      【解决方案2】:

      应该从套接字读取完整的缓冲区,然后解析它们。

      可以创建一个 MTU 大小的缓冲区,从套接字读取到这个临时缓冲区,然后解析完整的缓冲区,然后采取行动。

      可以使用 select() 或 poll() 来检查数据是否存在于套接字中。有空时阅读。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-04
        • 2021-01-23
        • 2015-05-08
        • 1970-01-01
        • 2014-06-07
        • 1970-01-01
        相关资源
        最近更新 更多