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.
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).
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?
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);
}
}