1
votes
  1. start listening client with netcat -l
  2. go program opens a conn with net.DialTCP to said client.
  3. kill the netcat
  4. in go program, do conn.Write() with a []byte -> it runs fine without error!
  5. it takes another conn.Write to get the error: broken pipe

The first write is the one where data loss happens, and I want to avoid. if i only get an error I know i can just keep the data and try again later. I've seen https://stackoverflow.com/a/15071574/2757887 which is a very similar case and the explanation seems to apply here, but it still doesn't explain how to deal with the issue, if the tcp protocol I need to implement only does one-way communication.

I've sniffed the traffic with wireshark, and when i kill the netcat, I can see that it sends FIN to the go program, to which the go program replies with ACK. For some reason the go program doesn't immediately reply with it's own FIN - and i'm curious why that is, it might help with my problem - but there's probably a good reason for it.

Either way, from the "connection termination" section @ http://en.wikipedia.org/wiki/Transmission_Control_Protocol, I conclude that the socket is in the CLOSE_WAIT state at this point, which I also confirmed with "netstat -np", which shows the socket going from ESTABLISHED to CLOSE_WAIT after killing netstat.

Looking at wireshark, the first conn.write results in a packet with push and ack fields set, and of course my payload. this is the write that succeeds fine in go.

then the old socket that used to belong to netstat sends RST, which makes sure that as soon as i try to write in go (2nd write) it fails.

So my question is:

A) why can't I get an error on the first write? if the socket received the FIN and is in CLOSE_WAIT why does Go let me write to the socket and tell me all is fine?
B) is there any way I can check in Go whether the socket is in CLOSE_WAIT? and if so, I could for this purpose consider it closed and not do the write.

thanks, Dieter

1
Are you reading from the socket ? Reading will tell you about netcat closing the socket. (Note that this is how the socket API works, regardless of which language you use the 2. write signals an error)nos
How will it tell me? I just tried it out - and remember, it's one way communication in the tcp protocol - my results: * if i provide a byte array it just hangs (no one is writing the other end..) * if i provide an empty byte array, i get EOF both when the connection is established, as well as as in close_waitDieter_be
You will get EOF. Ofcourse, you'll have to do the reading concurrently with performing the writes.nos
I don't understand how this solution should work. Like I said, both cases (established and close_wait) give an EOF, so how to tell the difference between these cases?Dieter_be

1 Answers

3
votes

Fundamentally, a successful write only tells you that data has been queued to be sent to the other end. If you need to make sure the other end gets that data, even if the connection closes or errors, you must store a copy of the data until the other end provides you with an application-level acknowledgment.