Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/58.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何判断套接字缓冲区是否已满?_C_Sockets - Fatal编程技术网

C 如何判断套接字缓冲区是否已满?

C 如何判断套接字缓冲区是否已满?,c,sockets,C,Sockets,如何判断读套接字缓冲区已满还是写套接字缓冲区为空 有没有一种方法可以不用系统调用就获得套接字缓冲区的状态 更新:这个如何:我想在读套接字缓冲区已满或写套接字缓冲区为空时获得回调或信号。通过这种方式,我可以停止处理以允许更多的I/O在线路上发生,因为在线路上发送数据时,I/O绑定始终是一个问题 select()调用是检查读取缓冲区中是否有内容的方法。当它已满时就不会了(我想)。考虑到套接字的内核缓冲区存在于内核空间中,我怀疑没有系统调用的情况下,是否有任何方法可以请求大小。 使用syscalls,

如何判断读套接字缓冲区已满还是写套接字缓冲区为空

有没有一种方法可以不用系统调用就获得套接字缓冲区的状态

更新:这个如何:我想在读套接字缓冲区已满或写套接字缓冲区为空时获得回调或信号。通过这种方式,我可以停止处理以允许更多的I/O在线路上发生,因为在线路上发送数据时,I/O绑定始终是一个问题


select()
调用是检查读取缓冲区中是否有内容的方法。当它已满时就不会了(我想)。

考虑到套接字的内核缓冲区存在于内核空间中,我怀疑没有系统调用的情况下,是否有任何方法可以请求大小。
使用syscalls,您可以使用PEEK尝试recv

ret = recv(fd, buf, len, MSG_PEEK);

将进行recv,但不清空缓冲区。

如果没有系统调用,这是不可能的。但是syscalls有什么问题吗?

使用
select
轮询文件描述符,并且超时为零-如果select说它是可写的,则发送缓冲区未满

(哦……没有系统调用。不,没有。)

附录:


为了回答更新后的问题,您可以在TCP套接字上使用两个
ioctl
s:
SIOCINQ
返回接收缓冲区中未读的数据量,
SIOCOUTQ
返回发送队列中未发送的数据量。但是我不相信有任何异步事件通知,这将使您不得不进行轮询。

您可以尝试
ioctl
。FIONREAD告诉您可以立即读取多少字节。如果这与缓冲区大小相同(您可以通过另一个icotl调用检索和/或设置缓冲区大小),则缓冲区已满。同样,如果可以写入与输出缓冲区大小相同的字节数,则输出缓冲区为空

我不知道FIONREAD、FIONWRITE和SIOCGIFBUFS(或同等产品)的支持范围有多广。我不确定我是否使用过它们,尽管我有一种偷偷的感觉,我出于某种原因在Symbian上使用过类似的功能

调用是否需要内核模式来计算这是特定于平台的。模糊地试图避免系统调用不是有效的优化技术

一个基本的BSD样式的套接字接口没有太多关于读写缓冲区的内容。何时发送缓冲区是否为空有关系?当然,这并不意味着所有数据都是在套接字的另一个端点接收到的——它可能位于某个路由器的某处。同样,“您的”读取缓冲区已满并不保证另一端的写入将被阻塞


一般来说,您只需尽可能多地读/写,并让套接字层处理复杂性。如果您看到很多I/O都是用小尺寸完成的,那么可能存在一些性能问题。但是请记住,流套接字将一次发送/接收包含一个数据块的数据包。除非设置了TCP_节点延迟,否则就不会出现字节逐个到达NIC的情况,最终可能会导致每个字节进行一次读取调用。它们是以数据包的形式到达的,所以很有可能一次就可以读取所有数据包,一次可以读取1k个。在有很多东西要读之前,你不太可能通过推迟阅读来加快速度。事实上,您可能会让情况变得更糟,因为当您的端点的读取缓冲区已满时,传入数据有被丢弃的风险,因为无处存储它,从而导致延迟和重新发送。

我认为您的方法有缺陷/注定失败的根本原因。系统不想告诉您读取缓冲区何时已满/写入缓冲区何时为空,因为这些事件表明您与系统之间的契约已破裂。如果事情发展到这一点(特别是在读取方向),那么要确保协议栈的顺利运行就太晚了。当您最终决定读取缓冲区时,可能会有更多的数据到达。您应该在缓冲区满之前读取缓冲区,这就是缓冲I/O的全部意义。

我知道这是一个古老的线程,但为了那些通过搜索引擎偶然发现这个问题的人的利益,我将回答这个问题,因为上面没有真正回答

在我开始之前,先克服系统调用挂起的问题——如果不切换内核空间,就无法与基于内核的(*nix)网络堆栈进行交互。您的目标应该是了解堆栈特性,以便能够从系统中获得最佳效果

如何判断读取套接字缓冲区是否已满

这部分已经得到了回答——你不知道,因为这不是你应该思考的方式

如果发送方正在(严重地)分割其TCP帧(通常是由于没有缓冲输出上的封送数据,并且使用TCP\u NDELAY关闭了Nagle算法),那么减少系统调用的数量是一个好主意。您应该使用的方法包括设置阅读的“低水印”。首先,通过使用setsockopt()设置SO_RCVBUF,确定您认为合理的接收缓冲区大小。然后使用getsockopt()读回实际的读取缓冲区大小,因为您可能无法得到所需的内容。:)不幸的是,并非所有的实现都允许您再次读取SO_RCVBUF,因此您的里程数可能会有所不同。接下来,在您想要读取数据之前,确定您想要呈现多少数据以供读取。使用setsockopt()将SO_RCVLOWAT设置为此大小。现在,套接字的文件描述符只有在至少有那么多数据要读取时才会选择为可读

或者写套接字缓冲区是空的

这是一个有趣的例子,因为我最近需要这样做,以确保我的MODBUS/TCP ADU每个都占用了自己的TCP帧,这是MODBUS规范所要求的(@steve:Control fragmentation是您需要知道发送缓冲区何时为空的一次!)。就原始海报而言