Subject: query: using two write() calls in succession

From: [email-masked]
Date: Mon, 26 Mar 2001 14:14:02 +0200

Hi, 

This problem is regarding use of  two write() call in succession. Let me explain the 
problem. In one of the blocking socket implementations, I have used two write calls mainly 
to detect the state of the TCP connection. I can expect that if the TCP connection has 
been closed (FIN) by the http server (due to http/1.1  timeout), the use of two write calls in sequence 
at the client side should detect if the connection was closed. As normally expected, when I 
make the first write() call, the server would ackowledge the client with a RST since 
the connection was  already closed. Now, when I make my second write() call, in 
succession, the presence of RST at the client TCP should prompt the second write() 
to fail and return with errno to ECONNRESET. I wrote a small code to check this behaviour.
I  ran this code in linux 2.2.16 to retrive the index.html page from an intranet web server.
In this code, I made a TCP connection to send and retrieve the index.html file normally and 
then slept for about 20 seconds allowing the web server to timeout.  After 20 seconds, after the
web server had timed-out and closed the connection, I again called the two writes (breaking the request)
 with the same GET HTTP/1.1 request in succession. 
I have some observations:

1. The second write() call in succession  does not fail. However, if I sleep for 1 second
in between the two writes, the second write() call fails and returns errno with ECONNRESET.
I checked this behaviour running it in Linux2.2.16/ SunOS _5.5.1/ 5.8 and the behavior remains same.
 However, in Sun OS 5.7, second write() call does not fail at all even after giving this delay. (I tried to
 increase the delay, but without any result). In VxWorks 5.2, we could detect the error in the second 
write call without any delay at all.

Q.1.1  Why do we need some delay for the second write() call to fail in most of the systems??
Q.2 .1 Why do we see such inconsistencies in various TCP implementations? (maybe I am missing 
something)...

2. I checked the tcpdump output of Linux 2.2.16 and I find that when I make the second write call
and after the client has received RST from the first write , the client TCP generates it own RST to be 
sent to the server. I do think that this is not the expected behaviour from the TCP. I checked the tcpdump
output running the same code in SunOS 5.7 and I dont find any RST being returned from the client to 
the server, after it itself has received the RST. This is the normal expected behavior of TCP, which 
is somehow not evident in Linux (I have included the tcpdump file; linuxdump.txt)

Q.2.1 Is there some problems in the 2.2.16 TCP stack of Linux that prompts it to return RST for an RST 
when the second write() call is made ??

Maybe I am missing something important or my interpretation of the problem. 
Would really appreciate your comments.

Regds,
Rajiv Chakravorty 

Philips Advanced Systems and Applications Labs (ASA-Labs)
Eindhoven, The Netherlands     [email-masked]

ps: appended, please find the tcpdump(linuxdump.txt) for linux and
the sampe code (testsock2.cpp) code used in this process.
for compilation and final executable:  g++ testsock2.cpp -o testsock -lnsl -lsocket
for accessing the server use:  testsock  <webserver>  <file to be retrieved>

---

From: Rick Jones <[email-masked]>
Date: Mon, 26 Mar 2001 10:40:44 -0800

[email-masked] wrote:
> problem. In one of the blocking socket implementations, I have used two write calls
> mainly to detect the state of the TCP connection. I can expect that if the TCP
> connection has been closed (FIN) by the http server (due to http/1.1  timeout), the

Um, isn't the remote's sending of a FIN supposed to generate a
zero-length read to inform the other side that there was at least a
partial shutdown?

> use of two write calls in sequence at the client side should detect if the connection
> was closed. As normally expected, when I make the first write() call, the server
> would ackowledge the client with a RST since the connection was  already closed. Now,
> when I make my second write() call, in succession, the presence of RST at the client
> TCP should prompt the second write() to fail and return with errno to ECONNRESET. I
> wrote a small code to check this behaviour. I  ran this code in linux 2.2.16 to
> retrive the index.html page from an intranet web server. In this code, I made a TCP
> connection to send and retrieve the index.html file normally and then slept for about
> 20 seconds allowing the web server to timeout.  After 20 seconds, after the web
> server had timed-out and closed the connection, I again called the two writes
> (breaking the request) with the same GET HTTP/1.1 request in succession.

> 1. The second write() call in succession  does not fail. However, if I sleep for 1
> second in between the two writes, the second write() call fails and returns errno
> with ECONNRESET. I checked this behaviour running it in Linux2.2.16/ SunOS _5.5.1/
> 5.8 and the behavior remains same.  However, in Sun OS 5.7, second write() call does
> not fail at all even after giving this delay. (I tried to  increase the delay, but
> without any result). In VxWorks 5.2, we could detect the error in the second write
> call without any delay at all.

As derMouse pointed-out, once you send the first segment, there is arace
between the other side getting the RST to the sending TCP, and the
sending app getting the second write into TCP.

As for why no delay was required in VxWorks, I'll hazard the guess that
the system running VxWorks was slow enough that the RST arrived before
the second segment could be sent by the app. 

As for why SunOS5.7 never got the ECONNRESET, probably a bug in 5.7.

I still think that paying attention to the zero-length read to detect
remote (graceful) close is best. doing things that elicit RST's is not
such a hot idea.

rick jones
-- 
ftp://ftp.cup.hp.com/dist/networking/misc/rachel/
these opinions are mine, all mine; HP might not want them anyway... :)
feel free to email, OR post, but please do NOT do BOTH...
my email address is raj in the cup.hp.com domain...