Hello All
This is my first proper post to the Arduino forums so please be gentle!
I'm using an Arduino Uno and the W5100 Ethernet Shield to do some hardware control using TELNET. I've written the server code using Arduino V1.0 and I'm using the standard Ethernet library as shipped with the IDE. The concept works fine - type commands into a TELNET server and things happen, with responses fed back up the wire to the client - but I need to do some form of link loss detection and make-safe a couple of seconds after the link fails.
What I was hoping to do was to send a TCP KEEP_ALIVE function to the client and check for an ACK response. As a proof of concept I added some code to the EthernetServer and W5100 libraries to send the KEEP_ALIVE command but I'm struggling when it comes to confirming that an ACK was received by the W5100.
I've done a search through the forums and can't find anything that relates to what I'm trying to do, so I'd be grateful for any help that you can offer!!
I've been through the W5100 datasheet and it seems that when I write a SEND_KEEP to SnCR (Socket n Command Register), the W5100 should send a TCP KEEP_ALIVE packet and await receipt of the ACK response. According to the datasheet, failure to receive an ACK within a given timeout should cause the KEEP_ALIVE packet to be re-transmitted until a resend limit is reached, after which the TIMEOUT bit of SnIR (Socket n Interrupt Register) to be set. The re-transmit interval is set in the RTR register and the resend limit is set by RCR. In my case, RTR is set to 0x07D0 (200mS) and RCR is set to 0x08 - I've written a function to read these registers and can confirm that that's the values they hold.
My hacked code checks to see whether there's an active connection, then writes SEND_KEEP to SnCR and reads SnCR until it clears (which should indicate successful receipt of an ACK). Whilst waiting, a do/while loop reads SnIR to see if the TIMEOUT bit is set and, if so, returns an error. Assuming that SEND_KEEP completes normally, which should indicate that the ACK packet was received, the function also returns normally. I have the Arduino Shield and a couple of PCs on a Network Hub so I can monitor the traffic to see what's going on (one PC is running the TELNET client, the other is the Wireshark sniffer).
So, my main sketch polls a send_keep_alive function every 750mS to check for link integrity and when the link is up, the KEEP_ALIVE and ACK packets are sent and received normally. When I pull the link to the TELNET client PC, the W5100 firstly sends 3 KEEP_ALIVE packets at 750mS intervals (from the sketch) then the time period expands and the W5100 starts retransmitting bytes of old (stale) data at 5 second intervals for the next 25 seconds or so, after which the W5100 pulls the plug and closes the socket. During this, SnCR/SEND_KEEP completes normally and the SnIR/TIMEOUT bit is not set until the socket is closed! The stale data is information previously sent from Arduino to the TELNET client and can be either information type in, or the initial TELNET/IAC (setup) commands if nothing has been typed.
I've thrown loads of debug strings in to write status details to the Serial port, and it seems like SEND_KEEP returns OK and the TIMEOUT bit is not set, regardless of whether an ACK was received. I only seem to get TIMEOUT is when the socket is forcefully closed, around 30 seconds after the link fails.
I don't think I'm doing anything stupid in my code and I even put a message an Wiznet's Q&A to which they replied, confirming that the information in the datasheet is correct.
I'm now at a loss and I was wondering if anyone else has used SEND_KEEP to check/confirm link integrity and, if so, how did you get it to work?!
I can post the code I've used but I'm new to the Arduino forum and didn't want to put to much up on my first real post.....
Regards
Derek.