Problem - more use Ethernet.begin and NTP client

Hello,

In my sketch I use refresh IP addresses from DHCP. The problem is when I want to use NTP client to retrieve time. When I used second ethernet begin the program freezes when executing a command Udp.endPacket (); . It somehow prevent this? Thank you for your advice I really do not know what to do with it.

I use mega 2560 R3 and ethernet shield r3 with wiznet w5100.

P.

Don't use second Ethernet.begin(). If you want to renew the DHCP lease, use Ethernet.maintain().

Thank you for the advice. It does not solve my problem. Trying to resolve the situation, when w5100 stop answer after few days. I tried it cooling, but it does not help. The solution would be if the Arduino knows that W5100 is dead send him a signal to turn on again. In my case, it is important to not restart the Arduino.

several months I try to solve freezing W5100 and I do not know if it's way. Now I want to try to ignore the freezing and try to start it again.

Go back though my forum posts looking for stuck ethernet sockets. Just yesterday i posted a reference to another forum that may have the answer listed.

On the w5100 sockets can get permanently stuck and when all the sockets are stuck no browser clients will be able to connect to your Arduino web server website.

In my past posts on here you will find my description of a way to identify stuck sockets and disconnect them so you can eliminate the problem.

I also use UDP NTP every day - it fails if all the sockets are stuck but works just fine if stuck sockets are disconnected shortly after they occur.

Cheers

Catweazle NZ

ok I read the thread on the forum what you sent. I try to use

---client.println("Connection: close");----

as there must be someone writes it helps. I also did not delay (1); between client.flush and client.stop. I add tracking sockets and write if it solved the problem. thanks

CatweazleNZ:
On the w5100 sockets can get permanently stuck and when all the sockets are stuck no browser clients will be able to connect to your Arduino web server website.

I cannot reproduce this failure. I can get most other server example sketches to fail, but in a way that locks up the sketch, not causes a socket to be "permanently stuck".

Is your server exposed to the internet, or on a localnet only?

edit: When the socket is stuck, what is that socket's status? Is it 0x17?
I think I just recreated the error. If I connect, don't send anything, and break the connection, the socket is "stuck".

Would you be kind enough to post your fix? The regular forum search function is down, or I would look it up myself.

SurferTim:
I cannot reproduce this failure. I can get most other server example sketches to fail, but in a way that locks up the sketch, not causes a socket to be "permanently stuck".

Is your server exposed to the internet, or on a localnet only?

edit: When the socket is stuck, what is that socket's status? Is it 0x17?
I think I just recreated the error. If I connect, don't send anything, and break the connection, the socket is "stuck".

Would you be kind enough to post your fix? The regular forum search function is down, or I would look it up myself.

During my early investigations of this issue I determined that I likely had a socket problem. I found some code to extract socket information. That helped me to observe that some sockets were stuck - the same IP address, the same destination port, the same socket status. You can see my socket status web page at http://www.2wg.co.nz/11540/

This code fragment is extracting the data for the web page:

char l_buffer[4] = "";
  for (uint8_t l_socket = 0; l_socket < MAX_SOCK_NUM; l_socket++) {
    G_EthernetClient.print(F("<tr><td>"));

    //Socket #
    G_EthernetClient.print(l_socket);
    G_EthernetClient.print(F("</td><td>"));

    //Status
    uint8_t l_status = W5100.readSnSR(l_socket);
    sprintf(l_buffer,"%x",l_status);
    G_EthernetClient.print(l_buffer);
    G_EthernetClient.print(F("</td><td>"));

    //Port In
    G_EthernetClient.print(W5100.readSnPORT(l_socket));
    G_EthernetClient.print(F("</td><td>"));

    //IP Address
    uint8_t dip[4];
    W5100.readSnDIPR(l_socket, dip);
    for (byte j=0; j<4; j++) {
      G_EthernetClient.print(dip[j]);
      if (j<3) 
        G_EthernetClient.print(".");
      //
    }
    G_EthernetClient.print(F("</td><td>"));

    //Port Out (destination)   
    G_EthernetClient.print(W5100.readSnDPORT(l_socket));
    G_EthernetClient.print(F("</td></tr>"));

  } //for each socket

I then set about capturing connected socket status information every five minutes. With a record of socket information my system could disconnect stuck sockets after ten minutes.

I define these global variables:

unsigned long G_SocketCheckTimer = 0;
extern unsigned long G_SocketConnectionTimers[MAX_SOCK_NUM]; //system millis
extern unsigned long G_SocketConnectionTimes[MAX_SOCK_NUM];  //time hh:mm:ss

I initialise the above variables in setup() as follows:

//Initialise the connected socket arrays
G_SocketCheckTimer = millis();
for (byte l_sock = 0; l_sock < MAX_SOCK_NUM; l_sock++) {
  G_SocketConnectionTimers[l_sock] = 0;
  G_SocketConnectionTimes[l_sock] = 0;
}

And within the loop() procedure I call this function to extract connected socket data, disconnect them after ten minutes and report the disconnection by email and activity log records:

void CheckSocketConnections() {
  if (G_EthernetClientActive == true) {
    //Exit if there is an active ethernet connection
    Pop(c_proc_num);
    return;
  }

  if (CheckSecondsDelay(G_SocketCheckTimer, C_OneMinute * 5) == false) {
    //Exit if five mins not elapsed
    Pop(c_proc_num);
    return;
  }

  //Check the current status of the sockets  
  for (uint8_t l_sock = 0; l_sock < MAX_SOCK_NUM; l_sock++) {
    uint8_t l_status = W5100.readSnSR(l_sock); //status
    if (l_status != 23) { //HEX 17 - Force timer reset
      G_SocketConnectionTimers[l_sock] = 0;
      G_SocketConnectionTimes[l_sock] = 0;
    }  
    else if (G_SocketConnectionTimes[l_sock] == 0) {
      //If the socket timer is not active but it is currently connected
      //then we start the socket timer and record the current (start) time.
      G_SocketConnectionTimers[l_sock] = millis();
      G_SocketConnectionTimes[l_sock] = Now();
    }
  }

  //Now check to see if any connected sockets have been running for ten minutes
  boolean l_reset_reqd = false;
  unsigned long l_timer; 
  for (uint8_t l_sock = 0; l_sock < MAX_SOCK_NUM; l_sock++) {
    l_timer = G_SocketConnectionTimers[l_sock];
    if ((G_SocketConnectionTimers[l_sock] != 0) && (CheckSecondsDelay(l_timer,C_TenMinutes))) //l_timer reset to zero at timeout
      l_reset_reqd = true;
    //
  }    

  //If there are any sockets that have been connected more than ten minutes 
  //then we will force a disconnection
  if (l_reset_reqd == true) {
    //First list the socket status in the activity file (sonnection time will show)
    ListSocketStatus();

    byte l_email_OK = EmailInitialise(EPSR(E_SOCKET_DISCONNECTION_25));
    String l_line = "";
    l_line.reserve(32);
    //Now disconnect the sockets that have been connected more than ten mins
    for (uint8_t l_sock = 0; l_sock < MAX_SOCK_NUM; l_sock++) {
      if ((G_SocketConnectionTimers[l_sock] != 0) &&
        (CheckSecondsDelay(G_SocketConnectionTimers[l_sock],C_TenMinutes))) { 
        W5100.execCmdSn(l_sock, Sock_DISCON);
        //socket.disconnect(i);
        G_SocketConnectionTimers[l_sock] = 0; //already reset by CheckSecondsDelay
        G_SocketConnectionTimes[l_sock] = 0;
        l_line = EPSR(E_Socket_Num__26) + String(l_sock);
        l_line += " - Disconnected";
        ActivityWrite(l_line);
        //Full details of disconnected sockets are saved in the activity log
        if (l_email_OK == 0) {
          EmailLine(l_line);
        }
      } //disconnect current socket (timed out 10 mins)
    }  //iterate across each socket
    if (l_email_OK == 0)
      EmailDisconnect(); //SENDS
    //
  }  //socket connection resets reqd

  G_SocketCheckTimer = millis();
} //CheckSocketConnections

This code lists socket information in my systems activity log when ever I do a disconnection.

void ListSocketStatus() {
/*
  static const uint8_t CLOSED      = 0x00;
  static const uint8_t INIT        = 0x13;
  static const uint8_t LISTEN      = 0x14;
  static const uint8_t SYNSENT     = 0x15;
  static const uint8_t SYNRECV     = 0x16;
  static const uint8_t ESTABLISHED = 0x17;
  static const uint8_t FIN_WAIT    = 0x18;
  static const uint8_t CLOSING     = 0x1A;
  static const uint8_t TIME_WAIT   = 0x1B;
  static const uint8_t CLOSE_WAIT  = 0x1C;
  static const uint8_t LAST_ACK    = 0x1D;
  static const uint8_t UDP         = 0x22;
  static const uint8_t IPRAW       = 0x32;
  static const uint8_t MACRAW      = 0x42;
  static const uint8_t PPPOE       = 0x5F;
*/

  //byte socketStat[MAX_SOCK_NUM];
  ActivityWrite(EPSR(E_ETHERNET_SOCKET_LIST_27));
  ActivityWrite(EPSR(E_Socket_Heading_28));

  //ActivityWrite("0=avail,14=waiting,17=connected,22=UDP");
  //ActivityWrite("1C=close wait");
  String l_line = "";
  l_line.reserve(64);
  char l_buffer[10] = "";
  for (uint8_t l_socket = 0; l_socket < MAX_SOCK_NUM; l_socket++) {
    l_line = " " + String(l_socket);
    uint8_t l_status = W5100.readSnSR(l_socket); //status
    //socketStat[l_socket] = l_status;
    l_line += " 0x";
    //l_buffer = "";
    sprintf(l_buffer,"%x",l_status);
    if (l_status != 23) { //HEX 17 Connected
      //The connection status has cleared since the last five minute check
      G_SocketConnectionTimers[l_socket] = 0;
      G_SocketConnectionTimes[l_socket] = 0;
    }
    l_line += l_buffer;
    l_line += " ";
    l_line += String(W5100.readSnPORT(l_socket)); //port
    l_line += " D:";
    uint8_t dip[4];
    W5100.readSnDIPR(l_socket, dip); //IP Address
    for (int j=0; j<4; j++) {
      l_line += int(dip[j]);
      if (j<3) l_line += ".";
    }
    l_line += " (";
    l_line += String(W5100.readSnDPORT(l_socket)); //port on destination
    l_line += ") ";
    if (G_SocketConnectionTimes[l_socket] != 0)
      l_line += TimeToHHMM(G_SocketConnectionTimes[l_socket]);
    //Serial.println(l_line);

    ActivityWrite(l_line);
  }
} // ListSocketStatus

I have not been able to reliably reproduce this problem - but it seems more frequent from connections that come a long way across the world and almost never on my local LAN.

It does seem to be the case that stuck sockets never get passed to the Arduino application via EthernetServer.available(). So apart from an IP address you do not get an HTML request to parse and analyse.

This link has a possible solution that I have not investigated:

http://forum.freetronics.com/viewtopic.php?t=176

If you have a look at my post over here on 10th August I alluded to a possible connection issue where no data is sent:

http://forum.arduino.cc/index.php?topic=252955.msg1837008#msg1837008

Hope all this helps. It would be useful if a resolution could be posted - along with the appropriate update to the w5100 or Socket library.

Cheers

Catweazle NZ

@CatweasleNZ: Thanks for the help on that, and posting your stuff. I'll take a look at it tomorrow. It's getting late here and I need some sleep.

I can reliably reproduce the fail any time I want. I played with it all afternoon. I use PuTTY to make the connection (port 80 in raw mode), don't send anything, then break the connection by disconnecting the ethernet cable from my computer for several seconds. I'm sure with a "software solution" I could do it much faster without the need to disconnect the cable.

edit: I imagine it could even be caused by a port scanner. If the scanner makes a connection and doesn't send a close message, that should do it.

Thank you, I use the web client on the Internet. from yesterday sockets only watching and waiting for freeze. I think that in a few days I'll have some data to evaluate and then try to use your code :slight_smile:

For now I have
Socket # 0: 0x22 D 8888: 129.6.15.28 (123) - NTP
Socket # 1: 0x0 D 8411: xx,239,201.17 (80) - my website that I read
Socket # 2: 0x0 1025 D: 172.41.10.15 (53) - DNS server - I do not know why there is
Socket # 3: 0x0 1033 D: 172.41.10.15 (53) - DNS server - I do not know why there is

Those port 53 sockets are the remnants of DNS resolution. As long as the socket status shows 0x0, you are ok.

So after a few days exploring the sockets I really encounters a problem with holding the socket. Although only one, but over time the problem would probably spread to others.
I have this condition permanently
Socket # 0: 0x22 D 8888: 129.6.15.28 (123)
Socket # 1: 0x17 D 3420: xx.239.201.17 (80)
Socket # 2: 0x0 3098 D: xx.239.201.17 (80)
Socket # 3: 0x0 1039 D: 172.41.10.15 (53)

I'm going to try the code that you wrote above. However, my problem with sockets showed up nearly a week, so it takes me a lot of time testing.

edit: W5100.execCmdSn (1, Sock_DISCON); - This command disconnects socket 1? So I can simply use every 5 minutes right?

Here is my fix that I incorporated into my playground web server sketch.
http://forum.arduino.cc/index.php?topic=277910.0
It closes the socket if it remains open for more than 30 seconds.

thank you, I'm going to try.

edit:

it appears that it works thanks :slight_smile:

After several weeks of testing, I noticed two cases of freezing despite using the above-written script.

The problem is as follows:

Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x0 16418 D:xx.239.201.17(80)
Socket#2:0x0 1028 D:172.41.10.15(53)
Socket#3:0x0 1031 D:172.41.10.15(53)
..
Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x17 16419 D:xx.239.201.17(80)
Socket#2:0x0 16420 D:xx.239.201.17(80)
Socket#3:0x0 1031 D:172.41.10.15(53)
..
Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x17 16419 D:xx.239.201.17(80)
Socket#2:0x17 16423 D:xx.239.201.17(80)
Socket#3:0x0 16428 D:xx.239.201.17(80)
..
Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x17 16419 D:xx.239.201.17(80)
Socket#2:0x17 16423 D:xx.239.201.17(80)
Socket#3:0x17 16432 D:xx.239.201.17(80)
..
Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x1C 16419 D:xx.239.201.17(80) - I think now script try disconect socket
Socket#2:0x17 16423 D:xx.239.201.17(80)
Socket#3:0x17 16432 D:xx.239.201.17(80)
..
Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x1C 16419 D:xx.239.201.17(80)
Socket#2:0x1C 16423 D:xx.239.201.17(80)
Socket#3:0x1C 16432 D:xx.239.201.17(80)

This is the end. Sockets stay in the state 0x1C. :frowning:
Does anyone know what to do?

Change the checkSockStatus function to this. Let me know how it does.

void checkSockStatus()
{
  unsigned long thisTime = millis();
  
  for (int i = 0; i < MAX_SOCK_NUM; i++) {
    uint8_t s = W5100.readSnSR(i);

    if((s == 0x17) || (s == 0x1C)) {
        if(thisTime - connectTime[i] > 30000UL) {
          Serial.print(F("\r\nSocket frozen: "));
          Serial.println(i);
          close(i);
        }
    }
    else connectTime[i] = thisTime;
    
    socketStat[i] = W5100.readSnSR(i);
  }
}

OK I try it. I'll report back if it helped. thanks

The 0x1C status indicates the socket is waiting for a close message from the client, but that may never come, at least in your case. I haven't experienced that situation yet, but I'm sure I would have eventually.

Let me know. If it works for you, I will modify my playground code to deal with that fail.

it's good :slight_smile: I guess it works.

Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x0 2634 D:xx.239.201.17(80)
Socket#2:0x1C 2594 D:xx.239.201.17(80)
Socket#3:0x0 1024 D:172.41.10.15(53)
..
Socket frozen: 2
Socket#0:0x22 8888 D:129.6.15.28(123)
Socket#1:0x0 2635 D:xx.239.201.17(80)
Socket#2:0x0 2594 D:xx.239.201.17(80)
Socket#3:0x0 1024 D:172.41.10.15(53)

I'll add it to my playground code. Thanks for letting me know. :slight_smile: