Unix Programming - close and O_NONBLOCK on TCP/IP socket in Linux

This is Interesting: Free IT Magazines  
Home > Archive > Unix Programming > February 2004 > close and O_NONBLOCK on TCP/IP socket in Linux





You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

Author close and O_NONBLOCK on TCP/IP socket in Linux
Torsten

2004-02-25, 2:34 pm

Hi

How can i make sure that all data queued for write on a socket with
O_NONBLOCK set is transmitted (or timeout reached) with a multiplexd
application using select()?

My problem is that if i call close with O_NONBLOCK set, the pending tx
data is discarded. If i call close with O_NONBLOCK cleared and
SO_LINGER set, my process blocks making it unresponsive to other
sockets.

Ideally i would want the kernel to keep trying to send data after
close until a timeout and silently deallocate the socket after send
completion or timeout.

Close manpage says: "If the O_NONBLOCK or O_NDELAY
flag is set, or if there are any pending signals, close()
does not wait for output to drain, and dismantles the STREAM
immediately."

socket manpage about SO_LINGER: "When enabled a close(2) or
shutdown(2) doesn't return until all queued messages for the socket
have been successfully sent or the linger timeout has been reached."

My problem is: if i use linger my process will block, if i use
O_NONBLOCK, my data will be discarded.

regards,
Torsten
David Schwartz

2004-02-25, 7:34 pm


"Torsten" <torsten-iversen@sol.dk> wrote in message
news:600802cf.0402251115.4244f8a9@posting.google.com...

> How can i make sure that all data queued for write on a socket with
> O_NONBLOCK set is transmitted (or timeout reached) with a multiplexd
> application using select()?


By closing down the connection gracefully.

> My problem is that if i call close with O_NONBLOCK set, the pending tx
> data is discarded.


Where did you see that?

> If i call close with O_NONBLOCK cleared and
> SO_LINGER set, my process blocks making it unresponsive to other
> sockets.


Correct.

> Ideally i would want the kernel to keep trying to send data after
> close until a timeout and silently deallocate the socket after send
> completion or timeout.
>
> Close manpage says: "If the O_NONBLOCK or O_NDELAY
> flag is set, or if there are any pending signals, close()
> does not wait for output to drain, and dismantles the STREAM
> immediately."


Which 'close' manpage is that? That's definitely not standard behavior.

> socket manpage about SO_LINGER: "When enabled a close(2) or
> shutdown(2) doesn't return until all queued messages for the socket
> have been successfully sent or the linger timeout has been reached."
>
> My problem is: if i use linger my process will block, if i use
> O_NONBLOCK, my data will be discarded.


I guess you'll have to call 'shutdown' and then wait for the shutdown to
complete in a non-blocking way. This is what you should be doing anyway,
otherwise what happens if other side sends some more data just before you
call 'close'?

DS


Torsten

2004-02-26, 12:34 pm

"David Schwartz" <davids@webmaster.com> wrote in message news:<c1jdfo$re2$1@nntp.webmaster.com>...
> "Torsten" <torsten-iversen@sol.dk> wrote in message
> news:600802cf.0402251115.4244f8a9@posting.google.com...
>
>
> By closing down the connection gracefully.
>
>
> Where did you see that?
>
>
> Correct.
>
>
> Which 'close' manpage is that? That's definitely not standard behavior.



Can't remember where. This one says the same:

http://www.scit.wlv.ac.uk/cgi-bin/mansec?2+close

Maybe i read it wrong. I guess the above behaviour only aplies to
STREAMS-based FD's (whatever that is).

I had another error in my program that made me think the problem was
with the way i called close, but now close appears to do what i want
it to do.

>
>
> I guess you'll have to call 'shutdown' and then wait for the shutdown to
> complete in a non-blocking way. This is what you should be doing anyway,
> otherwise what happens if other side sends some more data just before you
> call 'close'?
>
> DS


I guess they would get broken pipe, which is what they should get if i
disconnect. Obviously i do not close the stream before i have finished
reading what i am interested in from the peer.

I have searched the web but failed to find out how to "wait for the
shutdown to
complete in a non-blocking way.". Maybe i should just wait for select
to report the FD as writable after nonblocking shutdown of write?. But
then again, my info page (redhat 7.2 info pages:
Libc->Sockets->Open/Close Sockets->Closing a Socket) says about
shutdown:

quote

- Function: int shutdown (int SOCKET, int HOW)
The `shutdown' function shuts down the connection of socket
SOCKET. The argument HOW specifies what action to perform:

`0'
Stop receiving data for this socket. If further data
arrives,
reject it.

`1'
Stop trying to transmit data from this socket. Discard any
data waiting to be sent. Stop looking for acknowledgement
of
data already sent; don't retransmit it if it is lost.

`2'
Stop both reception and transmission.

end quote

My program does what i want it to if i call close after finishing
write (no shutdown), but i would prefer not to rely on behaviour that
is not explicitly stated in the manual. I am trying to find some
documentation that confirms that what i am doing is correct. In my
info pages i could find nothing about handling of pending transmit
data during close of a nonblocking socket.

Torsten
Barry Margolin

2004-02-26, 1:34 pm

In article <600802cf.0402260927.262f2af9@posting.google.com>,
torsten-iversen@sol.dk (Torsten) wrote:

> I have searched the web but failed to find out how to "wait for the
> shutdown to
> complete in a non-blocking way.".


You can't. If you need to be sure that the remote application has read
all the data before you close, you should implement this in the
application protocol.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***
David Schwartz

2004-02-26, 6:34 pm


"Torsten" <torsten-iversen@sol.dk> wrote in message
news:600802cf.0402260927.262f2af9@posting.google.com...

[color=darkred]
> I guess they would get broken pipe, which is what they should get if i
> disconnect. Obviously i do not close the stream before i have finished
> reading what i am interested in from the peer.



Actually, they'll get 'connection reset by peer', which will lead them
to believe that an error took place.


> I have searched the web but failed to find out how to "wait for the
> shutdown to
> complete in a non-blocking way.". Maybe i should just wait for select
> to report the FD as writable after nonblocking shutdown of write?. But
> then again, my info page (redhat 7.2 info pages:
> Libc->Sockets->Open/Close Sockets->Closing a Socket) says about
> shutdown:



No, keep selecting for 'read' and wait until 'read' returns zero. That's
how a closed connection is indicated to a non-blocking program.


> quote
>
> - Function: int shutdown (int SOCKET, int HOW)
> The `shutdown' function shuts down the connection of socket
> SOCKET. The argument HOW specifies what action to perform:
>
> `0'
> Stop receiving data for this socket. If further data
> arrives,
> reject it.
>
> `1'
> Stop trying to transmit data from this socket. Discard any
> data waiting to be sent. Stop looking for acknowledgement
> of
> data already sent; don't retransmit it if it is lost.
>
> `2'
> Stop both reception and transmission.
>
> end quote
>
> My program does what i want it to if i call close after finishing
> write (no shutdown),


If and only if the other side does not try to send any data before you
call 'close'.

> but i would prefer not to rely on behaviour that
> is not explicitly stated in the manual. I am trying to find some
> documentation that confirms that what i am doing is correct. In my
> info pages i could find nothing about handling of pending transmit
> data during close of a nonblocking socket.



Don't close the socket, shut it down and then wait for it to complete
the shutdown. Then and only then release the socket descriptor.

DS



Andrei Voropaev

2004-02-27, 4:34 am

On 2004-02-26, David Schwartz <davids@webmaster.com> wrote:
>
> "Torsten" <torsten-iversen@sol.dk> wrote in message
> news:600802cf.0402260927.262f2af9@posting.google.com...
>
>
>
>
> Actually, they'll get 'connection reset by peer', which will lead them
> to believe that an error took place.


Just to be clear in that. After local side is closed, remote shall get
FIN. If they don't read, but only write, then they won't see FIN, and
then they won't see Reset By peer and as final measure they will get
Broken pipe. If they read then they shall see FIN and stop sending.

>
>
>
>
> No, keep selecting for 'read' and wait until 'read' returns zero. That's
> how a closed connection is indicated to a non-blocking program.
>
>

[...]
>
> If and only if the other side does not try to send any data before you
> call 'close'.


Strange statement. This is true only if the application of OP is
interested in the data that remote sends. But according to the words of
OP the socket is closed after he got what he wanted. The rest of stuff is
not interesting for him. I assume that application of OP has done all
necessary things to warn remote side that connection will be closed
(this is the matter of politness though, not technical requirement).

>
>
>
> Don't close the socket, shut it down and then wait for it to complete
> the shutdown. Then and only then release the socket descriptor.


This is not absolutely necessary. It highly depends on the protocol.
Take for example HTTP 1.0. Client sends request and then to mark end of
request it does shutdown for write and keeps reading the socket. Server
after sending the response simply closes connection because it shall not
read anything else from client.

In SMPP protocol the side that wants to close the socket sends special
PDU to the peer, after getting response to that PDU, again it simply
closes the socket, without using shutdown, because there shall be
nothing else coming from the peer, and if someting comes then it is
problems of the peer.

The main point here is this. After application calls 'close' on the
stream socket, kernel makes sure that all the data in the buffers, and
the FIN packet are delivered to the peer. All incoming data for that
connection shall be thrown away and RST shall be sent (after the FIN was
sent). This is the behaviour of Linux 2.4.x. I can't speak for other
operating systems. The best for the OP would be to check man pages for
his system and not for unknown system in the internet.

Andrei
Sponsored Links






Free braindumps | Software forum | Database administration forum

Copyright 2003 - 2008 webservertalk.com