繁体   English   中英

无法通过多个“读取”调用从多播套接字读取 RTP 数据包(或获取其大小)

[英]Can't read RTP packet (or get its size) from multicast socket via several 'read' calls

我无法从使用以下函数打开的多播套接字读取 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)

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

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

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

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

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

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM