Hi,
Assuming I only need to read from 1 socket (hence select() only
requests for monitoring 1 read descriptor and nothing else), is there
a performance difference between using select() and read() at sub-
millisecond level?
Second question is: is true that read()/recv() is not reliable in
detecting a broken socket?
http://stackoverflow.com/questions/2245470/blocking-recv-call-hangs-if-server-is-down
I think I have run into a similar issue that read() just blocked but
another end actually closed the connection.
Any input is welcome :)
Thanks in advance.
|
|
0
|
|
|
|
Reply
|
hchan1980 (8)
|
2/19/2012 1:24:27 AM |
|
In article
<07d1a2ff-1f32-4237-a599-4fc0040c5274@n8g2000pbc.googlegroups.com>,
Hei <hchan1980@gmail.com> wrote:
> Hi,
>
> Assuming I only need to read from 1 socket (hence select() only
> requests for monitoring 1 read descriptor and nothing else), is there
> a performance difference between using select() and read() at sub-
> millisecond level?
Yes, doing two system calls is almost always slower than doing one.
>
> Second question is: is true that read()/recv() is not reliable in
> detecting a broken socket?
> http://stackoverflow.com/questions/2245470/blocking-recv-call-hangs-if-server-
> is-down
That page is basically correct. Read() will block until it receives
something -- either data, a FIN to indicate EOF, or a RST to indicate an
error on the socket. If the other machine crashes, it doesn't send
anything -- how can a down machine send something to tell you it's down?
And when it comes back up, it doesn't know anything about the
connections that were open during the previous boot, so it can't send a
RST to tell you about the error.
You should design your application protocol so that each end
periodically sends something, just an empty message if it has nothing
else to send. Then you can have a timeout -- if you don't receive
something, assume the other end crashed and close the connection.
>
> I think I have run into a similar issue that read() just blocked but
> another end actually closed the connection.
That shouldn't happen. If the other end closes the connection you
should detect EOF -- read() will return 0.
--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
|
|
0
|
|
|
|
Reply
|
barmar (5626)
|
2/19/2012 3:51:03 AM
|
|
On Feb 18, 7:51=A0pm, Barry Margolin <bar...@alum.mit.edu> wrote:
> In article
> <07d1a2ff-1f32-4237-a599-4fc0040c5...@n8g2000pbc.googlegroups.com>,
>
> =A0Hei <hchan1...@gmail.com> wrote:
> > Hi,
>
> > Assuming I only need to read from 1 socket (hence select() only
> > requests for monitoring 1 read descriptor and nothing else), is there
> > a performance difference between using select() and read() at sub-
> > millisecond level?
>
> Yes, doing two system calls is almost always slower than doing one.
>
ha. I just asked a dumb question. thanks.
>
> > Second question is: is true that read()/recv() is not reliable in
> > detecting a broken socket?
> >http://stackoverflow.com/questions/2245470/blocking-recv-call-hangs-i...
> > is-down
>
> That page is basically correct. =A0Read() will block until it receives
> something -- either data, a FIN to indicate EOF, or a RST to indicate an
> error on the socket. =A0If the other machine crashes, it doesn't send
> anything -- how can a down machine send something to tell you it's down?
> And when it comes back up, it doesn't know anything about the
> connections that were open during the previous boot, so it can't send a
> RST to tell you about the error.
>
> You should design your application protocol so that each end
> periodically sends something, just an empty message if it has nothing
> else to send. =A0Then you can have a timeout -- if you don't receive
> something, assume the other end crashed and close the connection.
>
Will setting SO_KEEPALIVE a better alternative than select()+recv()/
read()?
Checking the heartbeat at application level means I need a lock
somewhere...trying to speed up my application by avoiding locking :)
>
>
> > I think I have run into a similar issue that read() just blocked but
> > another end actually closed the connection.
>
> That shouldn't happen. =A0If the other end closes the connection you
> should detect EOF -- read() will return 0.
How about somehow my end (not my application) initiates a close?
What's the behavor?
Yes, it sounds a little bit weird. I went back to my application's
log, and it seems my recv() just hang there as if it was waiting for
data from the "alive" socket.
>
> --
> Barry Margolin, bar...@alum.mit.edu
> Arlington, MA
> *** PLEASE post questions in newsgroups, not directly to me ***
|
|
0
|
|
|
|
Reply
|
hchan1980 (8)
|
2/19/2012 4:45:03 AM
|
|
Hei , dans le message
<152252ff-1551-4f72-911e-023d101371d0@b9g2000pbo.googlegroups.com>, a
�crit�:
> Will setting SO_KEEPALIVE a better alternative than select()+recv()/
> read()?
Depends on how much time you are prepared to wait: the idle time before
SO_KEEPALIVE is usually 2�hours, plus about 1/4�hour for the various
retries, and can usually not be changed at application level (and should
probably not be changed system-wide): that may be acceptable for a
long-running daemon that does not do much, but never if there is an user
looking at the program.
|
|
0
|
|
|
|
Reply
|
george54 (194)
|
2/19/2012 8:22:23 AM
|
|
Le 19/02/2012 09:22, Nicolas George a �crit :
> Depends on how much time you are prepared to wait: the idle time before
> SO_KEEPALIVE is usually 2 hours
And beware of the infamous buggy router filtering SO_KEEPALIVE
packets... select()+recv() is probably a much more reliable way.
|
|
0
|
|
|
|
Reply
|
xroche (185)
|
2/19/2012 9:38:16 AM
|
|
Xavier Roche <xroche@free.fr.NOSPAM.invalid> writes:
> Le 19/02/2012 09:22, Nicolas George a �crit :
>> Depends on how much time you are prepared to wait: the idle time before
>> SO_KEEPALIVE is usually 2 hours
>
> And beware of the infamous buggy router filtering SO_KEEPALIVE
> packets...
I seriously doubt that any device whose purpose it is to forward IPv4
datagrams selectively drops IPv4 datagrams containing certain TCP
segments. Possibly, some stateful-inspection firewalls could do that
but these will break an idle connection after some time on their own,
anyway. Because of this and because of the very real possibilty that
stateful NAT is being used somewhere on the path, any application
protocol which is based on persistent connections needs to include some
kind of keepalive mechansism and 'TCP keepalives', insofar
implemented, are not really suitable for that: What is interesting is
not if the remote TCP still considers the connection valid but if the
remote application still replies. And this can only be ascertained by
sending an application protocol request and 'doing something about it'
when the expected reply wasn't received within some 'reasonable'
time.
> select()+recv() is probably a much more reliable way.
The 'much more reliable way' are end-to-end probes going from
application to application and 'select + recv' is the worst possible
way to implemented that[*] since it requires two system calls for
everything which is actually received no matter if keepalives are
needed or not. Three alternative choices would be:
1. Use the SO_RCVTIMEO socket option to cause a blocking read
to return with an EAGAIN error condition after some time has
passed without receiving data. Send a keepalive probe before
going back into read in this case.
2. Setup a periodic SIGALRM with some frequency and send a
keepalive probe after a read on the socket was interrupted for
some number of times without any data received in between.
3. Setup a periodic SIGALRM with some frequency, utilizing
automatic restarts of interrupted system calls. Maintain a
counter which is incremented from the signal handler and
cleared by 'the main program' whenever data was received from
remote. Send a keepalive probe from the signal handler
whenever the counter reaches a certain value.
[*] Just to mention this again: select is an 'optimized for 4.2BSD on
VAX-hardware' system call and it is hard to envision are more idiotic
data-passing interface between application and kernel, especially for
small descriptor sets for an environment where processes can have a
lot more than 32 open file descriptors and where frugal use of memory
is not the paramount concern anymore (proactive pessimization in
order to support operating environments whose vendors are presumably
not interested in good support for running portable applications is
also not very sensible).
|
|
0
|
|
|
|
Reply
|
rweikusat (2679)
|
2/19/2012 9:20:17 PM
|
|
|
5 Replies
50 Views
(page loaded in 0.151 seconds)
|