send() return?

Hi all.

I’m writing a TCP client that connect to a server and send data periodically. The server isn’t supposed to answer with an ACK (and I can’t change it).

I open the client socket as a blocking one and get send() return that it’s supposed to be the number of bytes sent. All works perfect until I unplug the server ethernet wire, the send function return a valid number of written bytes although obviously it isn’t.

If server side close connection with close() doing a send() at the client return -1 (it works). It only “fails” when I unplug the wire.

Somethings I try but doesn’t work:

  1. Set socket as non-blocking and select() it to know if write is possible. It says me it’s although it isn’t.

  2. poll() for POLLOUT event. Same as above.

  3. Set SNDBUFF to 0.

The only way I got it working is doing “Open-Send-Close” because when I try to reopen a non-connected server it warn me. But I want to avoid doing that if possible. Is there any way to know if destination of a open socket it’s up?

Thanks in advance.
Juanjo.

I believe the behaviour is valid. When the cable is removed, TCP/IP protocol assumes a problem on the network and tries to send the packet again after a certain time.

Hello again.

I don’t doubt this is the correct behavior of send. But it would be very useful for me know if destination is reachable when I send data.

Juanlogy,

Unfortunately that’s not possible with just plain TCP/IP.

This is why protocols were invented that send back acknowledgements that messages arrived.

The TCP/IP stack is designed to buffer packets for 30-40 seconds to handle temporary network cable disruptions.

You can try setting the SO_SNDTIMEO to a small value (less than a second) and that should cause the send() call to return with an error. Of course this may not actually be implemented under QNX because this is apparently one of the most widely non supported socket options.

Tim

This brings back memories. On one of my first projects involving QNX and TCP/IP I had the exact same surprise. We had two computers connected via TCP/IP and after unplugging the cable, the send() still returned without an error.

This is the correct behavior. Crazy as it sounds. TCP/IP provides no ACK or timeout to the user. What it provides is a guarantee that any packets you send will either appear correctly at the receiving end, or not at all.

If you do not like this, and you cannot add your own timeout/ACK then you are SOL.

I think you could try playing with the keep alive timeout but that`s a hack

Hi,

I guess you could try to do the following

  • Capture SIGPIPE
  • Disable TCP_NODELAY
  • Set SO_SNDBUF of equal length to the packages you send
  • SO_SNDTIMEO reduced to a small value
  • Enable SO_KEEPALIVE

Hi Gabriel, welcome!

Sorry to post this greeting publicly, but it is nice (and strange) to find here someone you know. :smiley:

Yes, I’m SOL (hehehe, i was looking for the meaning of).

I’ll try some hacks. If I get an elegant one I’ll post here.

Thanks you all.