我的C程序已从Linux上的TCP套接字读取(使用 read(2)或 recv(2))几个字节。是否有可能将这些字节推回,以便随后的 read(2)和 recv(2)调用(在我无法控制的库内深度发出)将读取他们又来了?
我知道 recv(2)的 MSG_PEEK 标志,如果推回原来是不可能的话,我将把它用作解决方法。< / p>
答案 0 :(得分:2)
最好的选择是更改工作流程,这样您就不需要阅读然后再推回数据。看起来两次看起来很丑陋(我同意这可能是合法的)。
但如果这不可能或非常困难,您可以使用read
(recv
)劫持LD_PRELOAD
和dlsym
系统调用。
答案 1 :(得分:2)
我所要求的似乎是不可能的。我最后用标志MSG_PEEK
调用recv()。这将使库中的后续recv()或recvmsg()调用读取相同的数据。
没有任何其他调用,我可以使用它来方便地只向前看一个字节。我们假设我需要向前看2个字节。我打电话给recv(fd, buf, 2, MSG_PEEK)
。如果2个字节中的1个已经到达,那么无论我多少次调用它,recv都会立即返回。我可以使用带有EPOLLIN | EPOLLET
的 epoll_ctl 来等待第二个字节。如果我想知道之后是否有EOF,我需要EOPLLIN | EPOLLET | EPOLLRDHUP
。 (请注意,EOF不会返回EPOLLHUP
。)因此,使用epoll_ctl
我可以避免在繁忙的轮询循环中调用 recv 来读取第二个字节。
我刚刚在我的Linux系统上验证过,默认情况下我可以通过这种方式查看大约900 kB的套接字。 (默认情况下,SO_RECVBUF
对我来说是1 MB,使用 setsockopt 减少它似乎会减少可以接收的数量,但不会减少一致数量。也许我减少它太晚了?)< / p>
即使MSG_PEEK
和EPOLLET
的组合也是一种解决方法,因为它们仍然不允许我将任意字节读取到套接字。他们让我做的只是偷看已经到达的字节而不消耗它们。