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; }
额外提示
- 若发送端是将宽高与图像数据合并为一个SRT数据包发送,建议接收端一次接收完整数据包后再解析,减少多次调用
srt_recvmsg的开销。 - 可通过
srt_setsockopt调整SRT的最大数据包大小,但需确保收发两端配置一致。
内容的提问来源于stack exchange,提问作者Harel
相关产品推荐
相关产品推荐

