0

I'm working on a network service and would like to be able to recover from dropped connections by caching the output I was trying to send so I can resend it when the client reconnects to the service. My service is using NSOutputStream wrapping a socket connection to send output to the client.

Is there any way to get confirmation of what data was successfully sent to the client? TCP should know how much made it to the other end, but I don't know how to get that information out of the NSOutputStream.

Can anybody give me pointers as to how I can manage this? Thanks!

EDIT: Alternately, is there a way to determine if the socket connection is still valid before I send my data? I'm using USB for the connection media, so it should be a very reliable link as long as the software on either side maintains the connection. But I don't get a socket closed event until after I've already tried to send the data.

Greg
  • 10,360
  • 6
  • 44
  • 67
  • TCP knows what was acknowledged by the remote stack, but I don't think any of the common APIs expose it to the caller. And if the connection failed after the packet was received, but the ACK failed, you could resend information that was already received. You should implement application-level acknowledgements, although the Two Generals problem means you can never get it perfect. – Barmar Feb 19 '13 at 17:15
  • I shouldn't need to worry about general packet loss, just an entire connection loss. Is there any way to determine whether the connection is still valid before I send data? The NSOutputStream's status is still reported as open and I don't get any events for the socket closing until after I try to send data through the stream. – Greg Feb 19 '13 at 17:21
  • Try to read before writing -- if the client has closed the connection, the read will return EOF. But there can still be timing problems, if they close the connection at the same time as you try to write. Your data and the FIN from the client will pass each other. Without application-level acknowledgements, there's no way to tell if the client closed the connection before or after receiving it. – Barmar Feb 19 '13 at 17:24
  • Hmm. I'm worried about interfering with my input stream getting data it needs from the socket, and if I call -[NSInputStream read:maxLength:] or read() with a length of zero I just get 0 bytes read, not an EOF. One of my writes is giving me a synchronous error, so I can use that as a workaround and resend all of the writes on reconnect.. Not ideal but it seems to be working. – Greg Feb 20 '13 at 15:32
  • Reading 0 bytes _is_ EOF. The basic problem is that networks are asynchronous. You can't tell before writing that there might be a FIN on its way to you. To avoid interfering with the input stream, check if your API has a "peek" or "pushback" operation. – Barmar Feb 20 '13 at 15:38
  • Okay, looks like I can use recv() to peek at the socket, but it is documented to block if the socket is open and there's no data yet. Do you know if I am safe to fcntl() the socket into non-blocking mode before I wrap it with the NSStreams? – Greg Feb 20 '13 at 15:46
  • I don't use the NSStreams API, so I can't answer that. – Barmar Feb 20 '13 at 15:55

0 Answers0