Pages: [1] 2   Go Down
Author Topic: Ethernet shield not allowing repeated connections  (Read 1849 times)
0 Members and 1 Guest are viewing this topic.
Glasgow
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hello all,

I'm having some trouble getting my new Ethernet Shield to make repeated connections to a php script hosted on my server.

I'm just starting out using the ethernet shield, and found some code at another post that looked like a decent starting point.

(My code will attached in the next post, as the forums won't let me include URLs in my first post)

the result from the serial window:
Code:
connecting...
connected
HTTP/1.1 200 OK
Date: Wed, 26 Nov 2008 15:50:47 GMT
Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch11
X-Powered-By: PHP/5.2.0-8+etch11
Content-Length: 27
Content-Type: text/html; charset=UTF-8

/nd101 /c1001 1 2 3 4   /et
disconnecting.
connecting...
connected
HTTP/1.1 200 OK
Date: Wed, 26 Nov 2008 15:51:06 GMT
Server: Apache/2.2.3 (Debian) PHP/5.2.0-8+etch11
X-Powered-By: PHP/5.2.0-8+etch11
Content-Length: 27
Content-Type: text/html; charset=UTF-8

/nd101 /c1001 1 2 3 4   /et

At this point, it just hangs -- indefinitely.

It always connects twice, gets the proper result, and then hangs.
Also, there is a delay of approximately 20 seconds between the printing of the first request ending and the printing of "disconnecting".

Also, if I press the reset button on the shield immeadately after the the first request is returned there is no hanging, and I can continue dozens of times with no troubles.

So, where to start looking for the trouble ?

Incidentally, the included web_client example will hang on "connecting.." if I press the reset button to restart the arduino.  If I disconnect it from the power instead of pressing the reset button, no problems.

Ultimately, I'm looking to send a request to my script every few seconds and parse the response.  So, if there is a better way to start working at this, I'm all ears.

Many thanks for any advice!
Logged

Glasgow
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

My code (as promised):
Code:
#include <Ethernet.h>

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192,168,0,51 };
byte server[] = {212,13,194,29};


Client client(server, 80);

enum CLIENT_STATE
{  
      STEP1, STEP2, STEP3, STEP4
};

static CLIENT_STATE client_state;

void setup()
{
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  
  delay(1000);
}

void loop()
{
  
  if (client_state==STEP1)
  {
    Serial.println("connecting...");
  
  if (client.connect()) {
    Serial.println("connected");
    
    client.println("GET /switchboard/switchtest.php?msg=%2Fnd101+%2Fc1001+%2Frq HTTP/1.1");
    client.println("Host: www.twentyeightninetyone.net");
    client.println("User-Agent: AVR ethernet");
    client.println("Accept: text/html");

    client.println();
  

    client_state=STEP2;
    delay(1000);
  } else {
    Serial.println("connection failed");
    delay(1000);
    client_state=STEP1;
  }
  }
  
  if (client_state==STEP2)
  {
  if (client.available()) {
    char c = client.read();
    Serial.print(c);
    client_state=STEP2;
  }
  else if (!client.connected())
  {    Serial.println();
    Serial.println("disconnecting.");
    client.stop();
    delay(3000);
      client_state=STEP1;
    }

  }
}
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 2
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Ben,

I just got my Ethernet Shield last week, and found the same problem.  It is a bug in the library, where all outgoing connections use the same TCP port number.

Most hosts ignore successive messages from the same port number.  To correct this, the port number must change with each successive connection request.  This can be corrected by modifying (see lines with PW comment) the client.cpp file located in /hardware/libraries/Ethernet folder, as follows.

Code:
extern "C" {
  #include "types.h"
  #include "w5100.h"
  #include "socket.h"
}

#include "Ethernet.h"
#include "Client.h"
#include "Server.h"

Client::Client(uint8_t sock) {
  _sock = sock;
}

Client::Client(uint8_t *ip, uint16_t port) {
  _ip = ip;
  _port = port;
  // 08-11-28 PW: Initialize source port
  _srcport = 0;
}

uint8_t Client::connect() {
  _sock = 255;
  
  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    if (getSn_SR(i) == SOCK_CLOSED) {
      _sock = i;
    }
  }
  
  if (_sock == 255)
    return 0;

  // 08-11-28 PW: Update source port
  _srcport++;
    
  // 08-11-28 PW: Use different source port each connection
  socket(_sock, Sn_MR_TCP, (_srcport + 1024), 0);
  
  if (!::connect(_sock, _ip, _port))
    return 0;
    
  while (status() != SOCK_ESTABLISHED) {
    if (status() == SOCK_CLOSED)
      return 0;
  }
  
  return 1;
}

Also, you will need to change the header file too add the variable to hold the source port number.

Code:
#ifndef Client_h
#define Client_h

#include "Print.h"

class Client : public Print {
private:
  uint8_t _sock;
  uint8_t *_ip;
  uint16_t _port;
  // 08-11-28 PW: Added
  uint16_t _srcport;
public:
  Client(uint8_t);


Cheers,

Paul...
Logged

Glasgow
Offline Offline
Newbie
*
Karma: 0
Posts: 3
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks Paul,

It worked!

Just for completeness: after making the changes you suggested, I also deleted all the .o files in the Ethernet directory to get them to recompile.  I don't know if that was necessary, but figured it couldn't hurt.

There are still some strange behavior with the sketch apparently hanging for about 20 seconds after it gets the last byte from the server.  I'll see if I can solve that issue myself.  If not, I'll start another thread.

Thanks again for your help!

--
Ben
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was getting a similar effect.  It would run for many hours sending a message about every minute then hang.

I did wonder why the interface does not have some kind of timeout around it so the application can try to resume?

Anyway, I applied the sugegsted port-changing mod. and we'll see what happens.

Actually I'm not sure the mod was applied.  I'm using the Mac version of the IDE and after changing and compiling did not see the timestamp change on the Client.o file (in the same folder as Client.cpp).  I'm note sure why.  Event renamed it, recompiled the app and got no error.  Maybe the IDE keeps it elsewhere?
Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did someone post a bug report on the software section?

-j

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

As I thought, my change had no effect.  It seems that the IDE does not recompile any changed library files. (The evidence is that Client.o was not touched.)

What's the easiest way on a Mac with OS/X 10.5.4 to just recompile a single library such as Ethernet?

I guess if this had been reported and fixed there would be a download available - even easier - but I suspect it has not been and I do not know how to initiate this myself.
Logged

0
Offline Offline
Faraday Member
**
Karma: 7
Posts: 2526
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
What's the easiest way on a Mac with OS/X 10.5.4 to just recompile a single library such as Ethernet?
Remove the .o files manually.

-j

Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Did that.  Still no new .o files created in hardware/libraries/Ethernet

Wondered if there's an issue with file permissions although I am the admin user.

The wierd thing is that the app sketch still builds!
Also searched the disk to find if the .o files are hidden elsewhere and found no others.

Any ideas pls?
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 21
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


There is one problem with this fix.  If you declare Client as a local variable to a routine and not global, then _srcport ends up being 0 everytime you connect:

void WriteData()
{
   Client client;
   client.connect();
   ...
   client.disconnect();
}

a new client is created with each call.  A fix to this is to make _srcport static.

Client.h

  static uint16_t _srcport;

Client.cpp:

uint16_t Client::_srcport = 0;

Also remove from Client::Client()

_srcport = 0;

I've made these changes and it's working well so far.  It used to hang after 4 loops, now it's at 30 and still going.

Michael


Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Still can't make the sketch with the modified Ethernet library.  Tried on WinXP - same problem.  Looked in hardware\cores\arduinoMakefile and can't see how it's pulling in the library - mind you, I haven't needed to use make for years.  Also looked for a Makefile for the library and only found a generic one.

You guys are modifying the library successfully - are you doing that with the standard Arduino IDE or whith what Makefile and on what platform?
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The Arduino IDE doesn't use the Makefile (which is there for people who don't want to use the IDE).  If you delete the .o files and quit and relaunch the IDE, it should recompile the libraries.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

OK Thx.  The problem was that I had renamed (not deleted) the .o files so that I could easily reverse the process.  Whatever the IDE does in the way of checking for the need to recompile does not allow for this (maybe a loose regexp).  Anyway, I moved them elsewhere and they were recompiled.  Now let's see whether it works as intended.

BTW.  In the event that it hangs for any other reason we'll still have a system in need of a manual reset - no good for unattended operation.  If anyone is changing the libraries it would be good to add an error path to avoid this.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Well, the port-changing mod enabled it to run for anywhere up to about 20 hours.  After that it got into a state where a call to client.available() always returned false (no matter how long I left it).  This happened several times.  The work-around I am trying is to detect that situation and in that case issue a call to Ethernet.begin().  We'll see whether this works.

  
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 12
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Still running 9 days later.  So the verdict is that you need the mod to the library and in your application code detect and treat the condition where it can get into that locked-up state.
Logged

Pages: [1] 2   Go Up
Jump to: