You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SRT套接字使用时出现异常报错问题求助

SRT套接字接收小数据报报错解决:LiveCC缓冲区过小问题

问题场景

使用Haivision SRT搭建服务端与客户端,连接建立正常,但接收自定义格式数据包时触发报错:LiveCC: buffer size: 2 is too small for the maximum possible 1316。自定义数据包结构为:width(2字节)、height(2字节)、RGB图像数据(widthheight3字节),代码逻辑要求先读取前4字节解析宽高,再接收后续图像数据,但调用srt_recvmsg接收2字节宽高时触发上述错误。

出错代码片段:

// _sock is the srt socket
typedef std::vector<Pixel> Image;

Image Viewer::receiveImage(uint16_t& width, uint16_t& height)
{
    int receivedBytes;
    char buffer[sizeof(uint16_t)];
    
    receivedBytes = srt_recvmsg(_sock, buffer, sizeof(buffer)); // 此处报错
    width = static_cast<uint16_t>(*buffer);
    receivedBytes = srt_recvmsg(_sock, buffer, sizeof(buffer)); // 此处报错
    height = static_cast<uint16_t>(*buffer);

    Image image(width * height * BITS_IN_BYTE);

    receivedBytes = srt_recvmsg(_sock, (char*)image.data(), image.size());
    if (receivedBytes <= 0)
    {
        throw std::runtime_error("Failed to receive stream from Sharer");
    }

    image.resize(receivedBytes);
    return image;
}

原因分析

SRT默认启用**LiveCC(实时拥塞控制)**模式,该模式要求接收缓冲区的大小至少能容纳SRT的最大数据包(默认值为1316字节,对应UDP MTU限制)。即使只需要接收2字节的数据,srt_recvmsg也会检查缓冲区是否足够容纳最大可能的数据包,否则就会触发报错。这是因为SRT基于UDP传输,数据包以整包形式传递,无法像TCP那样拆分小片段接收,必须提前预留足够的缓冲区空间。

另外,原代码还存在隐藏问题:直接用static_cast<uint16_t>(*buffer)转换宽高仅读取了单字节数据,且未处理网络字节序与本地字节序的差异,会导致宽高解析错误。

解决方案

方案1:扩展接收缓冲区至最小要求(推荐)

将接收缓冲区大小设置为至少1316字节,每次接收后仅提取需要的前2字节解析宽高,后续再处理图像数据。同时修复字节序转换问题。

方案2:关闭LiveCC模式(不推荐)

若无需实时拥塞控制,可通过srt_setsockopt关闭LiveCC,但这会失去SRT的核心拥塞优化能力,仅适用于低延迟无拥塞的局域网场景。

修改后的代码

// _sock is the srt socket
typedef std::vector<Pixel> Image;
const int SRT_MAX_PKT_SIZE = 1316; // SRT默认最大数据包大小

Image Viewer::receiveImage(uint16_t& width, uint16_t& height)
{
    int receivedBytes;
    char buffer[SRT_MAX_PKT_SIZE]; // 缓冲区设为最大数据包尺寸
    
    // 接收width
    receivedBytes = srt_recvmsg(_sock, buffer, sizeof(buffer));
    if (receivedBytes < sizeof(uint16_t)) {
        throw std::runtime_error("Failed to receive width");
    }
    uint16_t tempWidth;
    memcpy(&tempWidth, buffer, sizeof(tempWidth));
    width = ntohs(tempWidth); // 转换网络字节序到本地
    
    // 接收height
    receivedBytes = srt_recvmsg(_sock, buffer, sizeof(buffer));
    if (receivedBytes < sizeof(uint16_t)) {
        throw std::runtime_error("Failed to receive height");
    }
    uint16_t tempHeight;
    memcpy(&tempHeight, buffer, sizeof(tempHeight));
    height = ntohs(tempHeight); // 转换网络字节序到本地

    // 接收图像数据
    size_t imageSize = width * height * 3; // RGB每个像素3字节,替换原BITS_IN_BYTE(原定义可能有误)
    Image image(imageSize);

    receivedBytes = srt_recvmsg(_sock, (char*)image.data(), image.size());
    if (receivedBytes <= 0 || receivedBytes != imageSize)
    {
        throw std::runtime_error("Failed to receive complete image data");
    }

    return image;
}

额外提示

  1. 若发送端是将宽高与图像数据合并为一个SRT数据包发送,建议接收端一次接收完整数据包后再解析,减少多次调用srt_recvmsg的开销。
  2. 可通过srt_setsockopt调整SRT的最大数据包大小,但需确保收发两端配置一致。

内容的提问来源于stack exchange,提问作者Harel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:32:18