问题描述
我目前正在写一个代理应用程序从一个套接字读取和写入另一个。都被设置为非阻塞,允许多个套接字对成为手柄
I'm currently writing a proxy application that reads from one socket and writes on another. Both are set as non-blocking, allowing multiple sockets pairs to be handle.
要控制插座之间的适当流动,应用程序不应该从源头套接字读取如果目标插槽上的文字可能阻塞。
这个想法是好的,但是我发现没有办法检测目标插座的阻塞状态不先写吧...这是不是需要什么。
To control a proper flow between the sockets, the application should NOT read from the source socket if the writing on the target socket may block.The idea is nice, however I found no way to detect a blocking state of the target socket without first writing to it... and that is not what is needed.
我知道使用 SIOCOUTQ
选项(使用的ioctl()
),并计算出剩余的缓冲区,但相比于简单的检查,如果目标插座准备写这似乎难看。
I know of an option to use SIOCOUTQ
(using ioctl()
) and calculate the remaining buffer, but this seems ugly compared to a simple check if the target socket is ready for writing.
我想我也可以用选择()
只是这种插座,但就是这样一个沉重的系统调用这么多的浪费。
I guess I can also use select()
for just this socket, but that is so much waste of a such heavy system call.
推荐答案
感谢大家的反馈。
总结所有的意见和解答到现在为止:
Summarizing all comments and answers up until now:
直接的问题,唯一已知的方法来检测一个套接字将阻止在试图写它使用选择
/ 调查
/ 的epoll
。
Directly to the question, the only known way to detect that a socket will block on an attempt to write to it is using select
/poll
/epoll
.
最初的目标是建立一个代理,它从一个插座读取和写入到另一个,保持它们之间的适当平衡(读数在写作,反之亦然率相同),并使用的应用程序没有什么大的缓冲。为此,下列选项分别为presented:
The original objective was to build a proxy, which reads from one socket and writes to another, keeping proper balance between them (reading at the same rate of writing and vice versa) and using no major buffering in the application. For this, the following options were presented:
-
SIOCOUTQ
的使用,以找出多少缓冲留在目的地插座和传输不再多说。正如指出的 @ugoren 的,这具有不可靠的,在阅读的价值,计算并试图写入的实际值可能会改变的主要原因是不利的。它还介绍了忙等待的一些问题,如果错误地管理。我想,如果该技术被使用,但是应当后跟一个更可靠的一个用于全面保护。
Use of
SIOCOUTQ
to find out how much buffer is left on the destination socket and transmit no more than that. As pointed out by @ugoren, this has a disadvantage of being unreliable, mainly because in between reading the value, calculating it and attempting to write the actual value may change. It also introduces some issues of busy-waiting if wrongly managed. I guess, if this technique is to be used, it should be followed by a more reliable one for full protection.
选择
/ 调查
/ 的epoll $ C $的使用C>并添加每个读取插座的小有限缓冲液:最初,所有读套接字将被添加到
轮询
,准备用于读时,我们在有限的缓冲器大小读,然后从调查
读插座,而不是增加它的写作目的套接字,当我们回到调查
和我们检测到目标插槽中安装的写作,我们写的缓冲区,如果所有的数据是由插座接受,我们请从调查目的套接字,并返回读取插座回来。这里的缺点是,我们增加了系统调用的数量(添加/删除到调查
/ 选择
),我们需要保持每个插槽的内部缓冲区。这似乎是preferred方法,并可以添加一些优化,试图减少调用系统调用(例如,试图读取读插座之后写,且仅当东西留执行上述)。
Use of select
/poll
/epoll
and adding a small limited buffer per read socket: Initially, all read sockets will be added to the poll
, when ready for read, we read it in a limited buffer size, then remove the read socket from the poll
and add instead of it the destination socket for writing, when we return to the poll
and we detect that the destination socket is ready for writing, we write the buffer, if all data was accepted by the socket, we remove the destination socket from the poll and return the read socket back. The disadvantage here is that we increase the number of system calls (adding/removing to the poll
/select
) and we need to keep an internal buffer per socket. This seems to be the preferred approach, and some optimization could be added to try and reduce the call to system calls (for example, trying to write right after reading the read socket, and only if something is left to perform the above).
再次感谢大家参加这次讨论,对我帮助很大订货的想法。
Thank you all again for participating in this discussion, it helped me a lot ordering the ideas.
这篇关于非阻塞TCP套接字处理 - 如何检测写入到插座之前阻塞状态?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!