能否读取TCP写套接字缓冲区中的字节数?

4
我有一个应用程序,使用civetweb(以前是mongoose)HTTP服务器库创建MJPEG流。当我的MJPEG设置与客户端连接的网络的带宽配置文件匹配时,一切都运行良好,但偶尔我们会遇到低带宽连接,我想通过丢弃帧来适应它。
现在,当我调用mg_write()时,mongoose库会像这样调用send():
send(sock, buf + sent, (size_t) k, MSG_NOSIGNAL);

我想要做的是检查套接字的传出缓冲区,如果已满,则跳过一帧。有没有办法在应用程序级别检查这个?
编辑:对于MJPEG用户而言,这些TCP缓冲区非常大,我最终实际测量的只是缓冲区中是否存在任何字节。如果存在不止零个字节,则跳过一帧。
2个回答

4
您可以在Linux上使用ioctl(以及其他系统上的类似接口)来实现此功能:
#include <linux/sockios.h>

size_t sb_sz = sizeof(sock_buffer_size);
ioctl(sock, SIOCOUTQ, &bytes_in_queue);
getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sock_buffer_size, &sb_sz);
size_t bytes_available = sock_buffer_size - bytes_in_queue;

请注意,这仍然不能百分之百地保证写入操作会完全成功,但它可以为您提供相当大的成功机会。


1
你能提供一下 FIONSPACE 的参考资料吗? - fluter
@fluter,恰巧地,FIONSPACE在Linux上不可用。我已经编辑了适用于Linux的构造代码。 - SergeyA
getsockopt的第五个参数是一个输入输出参数,如果使用“sizeof(sock_buffer_size)”会导致编译错误。 - fluter
@flutter,说得对。我真的应该更注意这个答案。 - SergeyA
对于计划使用此功能的人,请注意:即使套接字已死,ioctl命令也会成功。 - mpr

-1
我想要做的是检查套接字的传出缓冲区,如果已满,则跳过一帧。有没有办法在应用程序级别检查这个?
当然可以,调用select()并查看套接字是否准备好写入。如果没有准备好,则表示套接字的传出缓冲区已满。(您可以使用select()的超时参数来强制使select()调用立即返回,如果您不希望它阻塞直到套接字准备好读取/写入等)

为什么不解释一下呢? - Jeremy Friesner
1
因为它会提示您可以发送至少一个字节。但是,OP不需要这个提示,他们需要知道是否可以发送整个帧(否则跳过它)。 - SergeyA
操作系统在套接字备份时允许对TCP套接字进行写入,因此真正的select()并不完全满足我的需求,尽管在其他情况下它可能有效。 - mpr
只需要做一点点工作就足够了:我的做法是保持一个先进先出队列,该队列存储着准备发送到套接字的传出字节。每当套接字通过 selects() 函数的 ready-for-write 参数准备好写入时,我将尽可能多的字节从 FIFO 队列中转移到套接字中。每当 FIFO 队列为空(而且我还有更多数据要发送时),我会向 FIFO 队列中倾倒另一个帧字节。 - Jeremy Friesner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接