On Sat, 10 Jul 2004, Shachar Shemesh wrote:

> The info pages.
>
> Do "info libc". Scroll down to "Function index". Search for "shutdown".
>
> It has a pretty detailed description of "close" sending all pending
> data, and then says:
>
> >   `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.

this looks inconcievable, because it implies that shutdown is a useless
function. i'd say this is a bug in the documentation. to demonstrate this,
i've done the following experiment.

- write a server that listens for a connection on a port, and when
  accept() returns a socket, read data from the socket until an EOF.
  after first passing the 1024*80 bytes (80KB) of data line mark, the
  server prints how much data it already got, goes to sleep for 10
  seconds and then continues reading. in the end it prints the total
  number of bytes (octets) it received.

- write a client that connects to a server, writes 200KB of data in 1024
  bytes chunks, with a 100ms sleep after each 1024 chunk was sent (either
  in a single write() or in multiple write()-s). after the 200KB were
  written, the client prints the number of bytes written, preforms a
  shutdown(s, SHUT_WR) on the socket, and goes to sleep for 100 seconds.

- run the above server. run the above client. in a terminal window,
  perform the following command repetedly, in order to see the
  kernel-level send-q and receive-q sizes.

  netstat -t | egrep 5050

  (5050 was the port on which my server listened).

  when the client got to its sleeping point (seen by the printing of the
  above-mentioned message), the above netstat command showed that the
  client's send-q is non-zero, for several seconds (until the server wakes
  up).

  after the server wakes up, the queues quickly got down to zero, and the
  server reported receiving a total of 200KB of data (i.e. the exact
  number of bytes that the client sent).

as i see it, shutdown() did NOT make the client discard the data stored in
its send-Q. this contradicts the glibc documentation which states that
shutdown will 'Discard any data waiting to be sent.'

you may also look at the source code of the 'tcp_shutdown' function in the
kernel, to see that it does not discard any data.

note: the numbers above were chosen because:

1. a socket on my system has a default queue size of ~64KB. thus, 120KB
   will fill the server's recv-Q when it sleeps and fill most of the
   client's send-Q.

2. the reason for the sleeps between sends, is to give the user (that's
   me) enough time to run netstat and read its output, even if i'm a
   little tired, and to see how the queues fill up.

3. the reason for the long-sleep on the server, is to give the
   (artifically slow) client enough time to finish sending its data before
   the server resumes reading data from the socket.

i'd suggest referring to the bible (W. richard steven's books about Unix
network programming) for proper explanations regarding the shutdown()
system call (i know, i know, on linux it's a specific function of the
socketcall system call. lets not get too pesky).

(... after a few minutes) ok, i took my own advice and checked the bible,
and it contradicts the info page - shutdown(s, SHUT_WR) will send a FIN
_AFTER_ sending any queued data, and will fail any _new_ writes to the
socket.

-- 
guy

"For world domination - press 1,
 or dial 0, and please hold, for the creator." -- nob o. dy

=================================================================
To unsubscribe, send mail to [EMAIL PROTECTED] with
the word "unsubscribe" in the message body, e.g., run the command
echo unsubscribe | mail [EMAIL PROTECTED]

Reply via email to