Ethernet shield doesn't detect TCP disconnection

Hello guys,

I've just started playing with ethernet shield and a C# software but i'm encounting the following (stupid and simple i hope ;)) issue:

HW used:

  • Duemilanove
  • Ethernet shield (W5100)

SW used:

  • Arduino 0021 (with original ethernet library)

SW description:
The arduino simply sends a sensor measure over ethernet network (TCP).
So the 'communication' part of code is only 4 "server.write(buffer[x])" lines (where x goes from 0 to 3).

It does not check for client (server.availlable) because the client (c# program) never sends data to server (arduino)! In fact the client connects to the arduino server and polls incoming data.

So the arduino calls 'server.write()' even if no client is connected and it's working fine whenever a client is connected or not.

The problem comes from the ethernet shield itself i think: when the software (computer) exits (with closing properly the TCP connection) it seems that the ethernet shield does not detect the disconnection!
Indeed, i've figured out that i can connect 1-4 times but never more!
The only way to connect again is reseting the ethernet shield.

Any ideas?

Many thanks in advance!

Geo.

hmmm...

26 reads and 0 idea, maybe this is not as simple/stupid as i expected :wink:

The short answer - the Arduino server should disconnect after it has completed sending data to the client (c# PC application). There are very simple examples that demonstrate this.

The long answer - The ethernet shield's only task is to place messages (ethernet packets) on the ethernet bus and pass on messages received with the proper MAC address to the Arduino server.

The shield has no knowledge of tcp, udp, or any other message protocol it is being used for. It never knows (or cares) if anything is listening at the other end.

I have seen tcp connects remain up for days (google tcp keepalive) after the connection at the other end has gone away (crashed).

Curt

Thanks for your reply!

Long question: If the shield never knows is listening to at the other end, how can i disconnect after sending data to the client???

Short question :wink: : how to disconnect!???

thanks in advance!

If the shield never knows is listening to at the other end, how can i disconnect after sending data to the client???

This is taken care of by the tcp protocol.

I have the ethernet shield but I haven't used it yet. The server examples that come with the IDE probably have your answer.

Curt

Actually, the shield is based on a chip that does know what a TCP connection is, and knows if it's been disconnected. The maximum number of concurrent connections is 4. If the remote device doesn't close the connection, it'll open up another one. There's actually quite a bit of discussion about this maybe a year or two ago, when the Ethernet library was updated to handle disconnects more elegantly. This would be called Ethernet2, I don't know if you're using it. The upshot is you need to manage the amount of connections you make.

It's hard to actually debug what's happening without the code, and how frequently you're making connections.

The ethernet shield does speak TCP - that's built into the WizNet chip, as the AVR just plain doesn't have the capacity (RAM) to do it well.

The WizNet chip can return status information, such as the other end disconnected (assuming it cleanly disconnected). However, it won't know if the other end just dropped off the planet - it doesn't implement keep-alives.

About all you can do is try to send something and see if you get the expected response within a certain (you pick) timeframe. If not, assume the other end disappears, close the connection (stop() if using the Arduino version of the library), and you should be good to go.

Personally, I had some issues with the built-in libraries (not low enough level for my taste), so I ended up going with Matt Robertson's ASocket library (awesome work, but definitely more difficult to use than the built-in IDE libraries). The only issue I had with that is if the WizNet received a SYN but no response to the SYN-ACK, it would simply sit there forever, without either being in the listening or connected state. Fortunately, a trip to the WizNet datasheet revealed that there is a SYN-RECEIVED state that you can test for (try an nmap -sS against the WizNet - it will eat a socket each time you run it unless you program a timeout handler in your code when status() != 0x14 but you expect the socket to be in a listening state), so if I remain in that state too long, I just close the re-initialize the socket. Not perfect, but good enough for an 8 bit micro with about as much memory as the size of the TCP packet that can be in the wire.

I think the ethernet board itself is a good board (I say this as someone with tons of TCP experience) - I'd be willing to stick it on a fairly open network without too much fear of it crashing. But I do kill any socket that sits around too long without activity. And I'm not as impressed with the Ethernet software libraries that come with the IDE, although I did find the examples worked as promised - so I don't think the libraries are that horrible.

If you try the WebServer code provided as an example with the IDE, do you have the same issue? If that works, but your code doesn't, it's not the shield or library, but rather your code. You are calling stop(), right?

Thanks all for your help!

No i don't use stop() because this command belongs to the client (arduino-side) class and i'm not using this!
I only use server.begin() and server.write() because the remote client (pc) never sends data so the arduino can't detect its connection with client.available().

By the way, i noticed that yesterday i could connect and disconnect 7-8 times without any problems but i don't know why it works sometimes and sometimes not...

NB: I use the original ethernet lib (0021).
NB²: I connect/disconnect manually (with 2 UI buttons) with, each time a few seconds before connecting/disconnecting...

Here is the code:

#include <SPI.h>
#include <Ethernet.h>
#include <CapSense.h>

// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 84, 3 };

#define encoderGSMask B00000001
#define encoderGSPin 8

// Initialize the Ethernet server library
Server server(8423);

void setup() {   

  pinMode(encoderGSPin, INPUT); //Encoder GS
  digitalWrite(encoderGSPin, HIGH);
  
  Serial.begin(115200);
  
  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  server.begin();  
}

void loop(){
    
    if ((PINB&encoderGSMask)==0)
    {
      server.write('S');   //Sync
      server.write(1);     //Rev 1
      server.write('B');   //Message Type
      server.write(0x01);  //Button ID

      delay(1000);
    }    
  }

Actually, the shield is based on a chip that does know what a TCP connection is, and knows if it's been disconnected.

Thank you for enlightening me - I was basing my response on experience with non Arduino/shield networking experience.

Curt

If you can narrow down what's going on or figure out a patch, please post it on the issues list: Google Code Archive - Long-term storage for Google Code Project Hosting.. The library definitely isn't perfect, so help is welcome.