Bug in Ethernet Library in new Arduino 0013

Can you post your code? What happens when you try to make the second connection?

I am having the same issue. It hangs the Arduino completely on the second connection attempt. Here is the code I am using:

#include <Ethernet.h>

// network configuration.  gateway and subnet are optional.
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
byte ip[] = { 192, 168, 1, 178 };
byte server[] = { 192, 168, 1, 54 };

Client client(server, 13000);

long timerX = 31000;

void setup()
{
  // initialize the ethernet device
  Ethernet.begin(mac, ip);
  Serial.begin(9600);
  Serial.println("Ethernet ChatServer Online");
}

void loop()
{
  if (client.available())
  {
    while (client.available())
    {
      char c = client.read();
      Serial.print(c);
    }
  }
  
  long currentTime = millis();

  if (abs(currentTime - timerX) > 10000)
  {
    Serial.println(timerX);
    if (client.connect())
    {
      client.println("Arduino Rocks!");
      timerX = millis();
      Serial.println("Client Message Sent");
    }
  }
}

Here is what I get back in the serial monitor:

Ethernet ChatServer Online

31000

Client Message Sent

ARDUINO ROCKS!

647

I have a simple tcplistener running on my computer that echoes back whatever it receives. As you can see it works on the first attempt and is about to attempt again after the 647. But, that is it, nothing happens after that. If the connect failed it should keep spitting out 647 until it connects because that value is not reset until a connection is made. So it seems the Arduino simply hangs at that point.

Hmm, there were a couple of changes in the library, and it would be good to isolate which one caused the problem.

Can you change the following line in hardware/libraries/Ethernet/Client.cpp (in the Arduino application directory) from:

socket(_sock, Sn_MR_TCP, _port, 1024 + _srcport);

to:

socket(_sock, Sn_MR_TCP, _port, 0);

Then delete hardware/libraries/Ethernet/Client.o and try recompiling and re-uploading your sketch. Do you see the same problem?

I made the change, but it still hangs on the second connection.

Can you change the following line in hardware/libraries/Ethernet /Client.cpp (in the Arduino application directory) from:

socket(_sock, Sn_MR_TCP, _port, 1024 + _srcport);

to:

socket(_sock, Sn_MR_TCP, _port, 0);

Should it not be

socket(_sock, Sn_MR_TCP, 1024 + _srcport, 0);

that is as this modification to the Client.cpp is listed in the orginal message by a "Paul_", see the posting with the title

"Ethernet Library Bug :: No Repeated Connections..."

on "page 2" on this forum?

I have not yet got around testing it myself though...

regards,

Hi,

Tested it with the code above, but modified to use the standard "echo" service on port 7. Got a few TCP connection listed as open before the code somehow went into a "loop" writing the number "31075" to the serial console...

inetutils 15945 root 3u IPv6 55938 TCP lupus.local:echo->10.0.0.177:1030 (ESTABLISHED)
inetutils 15946 root 3u IPv6 55939 TCP lupus.local:echo->10.0.0.177:1031 (ESTABLISHED)
inetutils 16067 root 3u IPv6 56394 TCP lupus.local:echo->10.0.0.177:1027 (ESTABLISHED)
inetutils 16068 root 3u IPv6 56395 TCP lupus.local:echo->10.0.0.177:1028 (ESTABLISHED)
inetutils 16069 root 3u IPv6 56396 TCP lupus.local:echo->10.0.0.177:1029 (ESTABLISHED)
inetutils 16072 root 3u IPv6 56529 TCP lupus.local:echo->10.0.0.177:1025 (ESTABLISHED)
inetutils 16074 root 3u IPv6 56567 TCP lupus.local:echo->10.0.0.177:1026 (ESTABLISHED)

regards,

kmm: I think you're right. Does changing that line make it work better than with the default Arduino 0013 library?

Hi,

Tested it with the original Client.cpp file and it do block, as originally reported by MFV.

Thinking of it it is not so strange as it with the line

socket(_sock, Sn_MR_TCP, _port, 1024 + _srcport);

will create a new 5-tuple for the IP connection that is identical to the previous one. And that will not work. Changing the line into

socket(_sock, Sn_MR_TCP, 1024 + _srcport, 0);

will on the other hand create a new unique 5-tuple (the originating port number changes) for the IP connection like it should do.

regards,

Hi,

I tested kmm's fix and it seemed to do the trick. But I was still having a problem my TCPListener program not receiving any subsequent messages because it still thought the first connection was open. I was able to get around this by adding a client.stop() after sending a message. Looking at it now it's probably better to use the client.connected() to see if you are still connected rather than creating a new connection each time. It may still be a good idea to add:

  if (connected())
    stop();

or maybe:

  if (connected())
    return 1;

to the begining of uint8_t Client::connect() in client.cpp? What do you guys think?

I went ahead and modified the library to be compatible with Sanguino. It tested fine with the modifications on both Arduino and Sanguino.

Good catch kmm!

Thanks guys.

Hello again,

ich changed
socket(_sock, Sn_MR_TCP, _port, 1024 + _srcport);
into
socket(_sock, Sn_MR_TCP, 1024 + _srcport, 0);
in hardware/libraries/Ethernet /Client.cpp

recompile my sketch but Arduino still send one request and stop then. Hm...

Whenever changing something in a library, remove all the *.o files in that library's folder. Then recompile (verify) your sketch.

Fin, it works.
Great job. Thanks.

Unfortunately, I spent an hour and a half up against this bug last night trying to figure out what I was doing wrong in my code. It didn't even occur to me that it might be a bug in the library. I figured it had to be my code, because, well, I'm new to this.

Glad to know it wasn't my code. An extra hour and a half of sleep would be nice, though.... :slight_smile:

I made those changes but I think I have another problem, after 5 connections (one after another ... not at the same time) ... the arduino refuses any connection for about a minute ? Is there something I should be calling to free up those connections, besides client.stop(); ?

How much time between connections? Can you post your code?

#include <Ethernet.h>


byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xEF, 0xED };
byte ip[] = {192, 168, 0, 10 };

int CurrentTime = 0;
const int TimeOutMax = 6000;

boolean DebugMode = true;

Server server = Server(23);


void setup()
{
  pinMode(StatusLED, OUTPUT);      // sets the digital pin as output
  digitalWrite(StatusLED, HIGH); 
  pinMode(Learner, INPUT);
  pinMode(IR1, OUTPUT);
  pinMode(IR2, OUTPUT);
  pinMode(IR3, OUTPUT);
  pinMode(IR4, OUTPUT);
  digitalWrite(StatusLED, LOW);
  delay(200);
  Ethernet.begin(mac, ip);
  server.begin();
  digitalWrite(StatusLED, HIGH);
  Serial.begin(9600);
  
}

void loop()
{
 Client client = server.available();
 if (client)
 {
   if (DebugMode)
   {
     Serial.println("Connected");
   }
   byte ReadyChar;
   
   ReadyChar = client.read();
  
   if (ReadyChar == 0)
   {

   }
   if (ReadyChar == 255)
   {
       client.write(255);
       GetCommandData(client);   
       client.stop(); 
   }
 }
 else
 {
   if (DebugMode)
   {
     Serial.println("Not Connected");
   }
 }
}

There is more too it if you want to see it all, but there is normally 10 seconds between connections (sometimes a little less or more). I timed the code to get from the Serial.println("Not Connected"); back to that statement after it connects transfers data and does it thing then back to saying "Not Connected" normally takes about 400 ms.

What are you using to connect to the Arduino? What exactly are you wanting it to do?

I'd try getting rid of that client.stop();

Seeing the rest of your code and knowing more about what you want to accomplish may help.

I will post the rest of it this evening, but I added the client.stop(); because it wasn't working (it didn't help)

I'm trying to send IR codes to the ardunio then have it flash an emitter to turn my TV on and off, I have an IPAQ running a .net app that takes a standard IR hex code converts it to number of burst pairs, clock speed, and an array or on times and off times. I want to send those to the arduino and once it has the complete information I want to it flash the emitter and send it (which all of that works) the problem comes when I want to send multiple IR codes in a row (example I want to scan though the guide or something ... pushing the guide button then the up or down arrow a couple times) thats when the .net application gets an error saying the arduino actively refused the connection

#include <Ethernet.h>


byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xEF, 0xED };
byte ip[] = {192, 168, 0, 10 };
int StatusLED = 2;                // Pin For Power Light
int Learner = 3;    
int IR1 = 4;                      // Pin For Top Left IR
int IR2 = 5;                      // Pin For Bottom Left IR
int IR3 = 6;                      // Pin For Top Right IR
int IR4 = 7;                      // Pin For Bottom Right IR

int incomingInt = 0;
int ClockSpeed = 0;
int OnesData = 0;
int TensData = 0;
int HunsData = 0;
int ThosData = 0;
int TThoData = 0;
int SendPort = 0;

int CurrentTime = 0;
const int TimeOutMax = 6000;

boolean DebugMode = true;

Server server = Server(23);


void setup()
{
  pinMode(StatusLED, OUTPUT);      // sets the digital pin as output
  pinMode(Learner, INPUT);
  pinMode(IR1, OUTPUT);
  pinMode(IR2, OUTPUT);
  pinMode(IR3, OUTPUT);
  pinMode(IR4, OUTPUT);
  Ethernet.begin(mac, ip);
  server.begin();
  digitalWrite(StatusLED, HIGH);
  Serial.begin(9600);
  digitalWrite(StatusLED, HIGH); 
}

void loop()
{
 Client client = server.available();
 if (client)
 {
   if (DebugMode)
   {
     Serial.println("Connected");
   }
   byte ReadyChar;
   
   ReadyChar = client.read();
  
   if (ReadyChar == 0)
   {

   }
   if (ReadyChar == 255)
   {
       client.write(255);
       GetCommandData(client);   
       client.stop(); 
   }
 }
 else
 {
   if (DebugMode)
   {
     Serial.println("Not Connected");
   }
 }
}

int TimeOut(Client client)
{
   CurrentTime = 0;
    do
    {
      if (CurrentTime > TimeOutMax)
      {
        if (DebugMode)
        {
          Serial.println("Comm Error");
        }
        return -1;
      }
      CurrentTime = CurrentTime + 1;
    } while (client.available() == 0);
    return 0;
}

int GetNumber(Client client)
{
  TThoData = 0;
  ThosData = 0;
  HunsData = 0;
  TensData = 0;
  OnesData = 0;
  
  if (TimeOut(client) != 0)
  {
    return -1;
  }
  TThoData = client.read();
  TThoData = TThoData * 10000;
 
  if (TimeOut(client) != 0)
  {
    return -1;
  }
  ThosData = client.read();
  ThosData = ThosData * 1000;
 
  if (TimeOut(client) != 0)
  {
   return -1;
  }
  HunsData = client.read();
  HunsData = HunsData * 100;

  if (TimeOut(client) != 0)
  {
    return -1;
  }
  TensData = client.read();
  TensData = TensData * 10;
 
  if (TimeOut(client) != 0)
  {
    return -1;
  }
  OnesData = client.read();
  
  return OnesData + TensData + HunsData + ThosData + TThoData;
}


void GetCommandData(Client client)
{
 
  byte ReadyChar;

    if (TimeOut(client) != 0)
    {
      return;
    }
    ReadyChar = client.read();

    if (ReadyChar == 1)                  // Goto IR Data
    {
      client.write(255);
      GetIRData(client);
    }
}

void GetIRData(Client client)
{
  byte ReadyChar;
  if (TimeOut(client) != 0)
  {
    return;
  }   
  int TempPort = 0;
  TempPort = client.read();

  switch (TempPort)
  {
   case 1:
    SendPort = 4;
    break;
   case 2:
    SendPort = 5;
    break;
   case 3:
    SendPort = 6;
    break;
   case 4:
    SendPort = 7;
  }
   
  incomingInt = GetNumber(client);
  if (incomingInt == -1)
  {
    return;
  }
  
  ClockSpeed = GetNumber(client);
  if (ClockSpeed == -1)
  {
    return;
  }
   
  int OnTimes[incomingInt+1];
  int OffTimes[incomingInt+1];

  for (int count=0; count <= incomingInt; count++)
  {
 
    OnTimes[count] = GetNumber(client);
    if (OnTimes[count] == -1)
    {
      return;
    }
  
   OffTimes[count] = GetNumber(client);
    if (OffTimes[count] == -1)
    {
      return;
    }
   
  }
  
   for (int count1=0; count1 <= incomingInt; count1++)
   {
      TurnOn(OnTimes[count1]*2, SendPort);

      digitalWrite(SendPort, LOW);
      if (OffTimes[count1] < 16383)
      {
        delayMicroseconds(OffTimes[count1]);
      }
      else
      {
        delay(OffTimes[count1]/1000);
      }
    } 
}

void TurnOn(int time, int IRPort) 
{

  boolean PinOn = false;

  for (int C=0; C <= time; C=C+ClockSpeed)
  {
    if (PinOn == false)
    {
      digitalWrite(IRPort, HIGH);
      delayMicroseconds(8);//ClockSpeed);
    }
    else
    {
      digitalWrite(IRPort, LOW);
      delayMicroseconds(9);//ClockSpeed);
    }
    PinOn = !PinOn;
  }
}