Strange UDP bug

That would be because the socket closed by the timeout…but do it to0 fast and you use up all 7 sockets… I would keep the stop… hmmm on the receive side…I will think about that one and get back to you.

1 Like

Thank you for highlighting the timeout issue - it has saved me hours of barking up the wrong tree. I have a Spark server that will eventually deliver data to a number of other machines which are running python UDP client software.
As long as a request for service is made more often than every minute all is well.
On the client side it is easy to set a try/except expression on the error socket.timeout and fire up the socket again but on the server side I’m struggling and have a very untidy solution but is does seem stable and allows long delays between communications.

Python code for clients: (sorry I’ve not learned how to post code snippets proerly yet)
This runs reliably and keeps going if the server temporarily dies. It typically cycles through 4 socket object addresses if it never gets a response.

while True:
    s = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)   #Create a socket object
    print(s)
    s.settimeout(1)
    while s:                         
        s.connect((host, port))      # connect to server
        s.sendall(b'Ad Ready ')      # client ready for data
        print ('sent ready message')
        r='not read anything'
        try:
            r = s.recv(1024)      
        except socket.timeout:
            print('socket timeout')
            break
        if r == 0:          # if r is 0 then the sender has closed for good
            print('socket disconnected')
            print(s)
            break
        text = r.decode("utf-8")
        print(text)
        
        time.sleep(3)      #replaces  do something with data from server
    print('Out of inner loop')
    s.close()
    

and the messy Spark server code restarts the UDP socket every 50 seconds to bypass the 60 sec timeout…

void setup(){
  pinMode(D7,OUTPUT);         // Turn on the D7 led so we know it's time
  digitalWrite(D7,HIGH);      // to open the Serial Terminal.
  
  Serial.begin(9600);         // Open serial over USB.
  while(!Serial.available()); // Wait here until the user presses ENTER in the Serial Terminal
  digitalWrite(D7,LOW); // Turn off the D7 led ... your serial is serializing! 
  udp.begin(localPort);
  Serial.println("Waiting for request from client");
  lastRead = millis();
}
/* This function loops forever --------------------------------------------*/
void loop(){

    if (millis()-lastRead > 50000){
        lastRead=millis();
        udp.stop();
        delay(100);
        Serial.println("Restarting socket");
        udp.begin(localPort);
    }
    
    packetSize = udp.parsePacket();
    
    Serial.print(".");
    if(packetSize)
      {
        digitalWrite(D7,HIGH);
        Serial.print("Received packet of size ");
        Serial.println(packetSize);
        Serial.print("From ");
        remote = udp.remoteIP();
        for (i =0; i < 4; i++)
        {
          Serial.print(remote[i], DEC);
          if (i < 3)
          {
            Serial.print(".");
          }
        }
        Serial.print(", port ");
        Serial.println(udp.remotePort());

  // read the packet into packetBufffer
        udp.read(UDPincomingData,256);
        Serial.println("Contents:");
        Serial.println(UDPincomingData);

    // send a reply, to the IP address and port that sent us the packet we received
        udp.beginPacket(udp.remoteIP(), udp.remotePort());
        //put server data in UDPoutgoingData[] here ----------------
        udp.write(UDPoutgoingData);
        udp.endPacket();
        memset(&UDPoutgoingData[0], 0, sizeof(UDPoutgoingData));
        memset(&UDPincomingData[0], 0, sizeof(UDPincomingData));
        Serial.println("Waiting for request from client");
        }
     digitalWrite(D7,LOW);
     
  }
 

I hope this helps someone else to keep their socket communications alive and obviously I’d welcome enough extra library information to get the job done more neatly.

@phec would you mind editing your above post and doing this to your code, it will really help people see it and copy it :wink:

1 Like

OK thanks for the formatting information - I hope it looks better now. I see there are plenty of typos in the text too - sorry.
The code has been running for 24 hours now with frequent communications and for the past 5 hours with infrequent communication at > 1 minute intervals. So far so good. There have been over 300 socket restarts for the Spark so I think we can be sure that we’re not going to run out.

Looks great now! Thanks :smile: Without the formatting, it’s almost impossible to copy/paste the code without errors.

Hi!

I have only figured out there might be a timeout behaviour with UDP socket whilst working on my project last night. My solution for it was simply to call the begin() and stop() each time packets need to be sent:

void sendUDP(byte *cmd) {
  Udp.begin(localPort);
  Udp.beginPacket(remoteIp1, remotePort1);
  Udp.write(cmd, 2);
  Udp.endPacket();
  Udp.stop();
}

I am an absolute beginner working with Arduino and was wondering if there is any problem doing so, other than the possibly slower response?

Your fix is needed because the current firmware has a 60 Second inactivity timeout. So if the code does not execute faster then the the timeout, the socket closes. The call to begin() and stop(), ensures the socket is open when used.

Thanks @david_s5. I understand. My question was really just wanting to know, instead of implementing a check in the loop like the code others have contributed, anything wrong for calling the begin() and stop() methods each time UDP packets need to be sent. Isn’t that neater?

I think in the world of Arduino, the paradigm is usually setup() does the begin() and loop() uses the peripheral.

The code you have is 100% fine and in addition it keeps freeing 1 of the 7 total sockets (4 connected max) that the cc3000 (wifi chip) can support. The Spark Protocol uses 1 socket constantly and 2 if it testing the internet. So the paradigm you have is good resource management.

1 Like

Actually, an unsigned int has a range of :0 to 4,294,967,296. and an signed int is : 0 to +/- 2,147,483,648. We are working with a with a 32 bit micro....

David G.

You’re right! I usually always declare variables very specifically like uint8_t, uint16_t, uint32_t so I never question what I have. I had uint16_t in mind…

Just in case anyone wants to double check this type of thing for themselves, if you aren’t sure… you can use sizeof() to see how many bytes the data type consumes.

unsigned char char1 = 0;
unsigned int int1 = 0;
unsigned long long1 = 0;
double double1 = 1.0;

void setup() {
    Serial.begin(9600);
    while(!Serial.available());
    Serial.print("CHAR: "); Serial.println(sizeof(char1));
    Serial.print("INT: "); Serial.println(sizeof(int1));
    Serial.print("LONG: "); Serial.println(sizeof(long1));
    Serial.print("DOUBLE: "); Serial.println(sizeof(double1));
}

void loop() {

}

Returns:

CHAR: 1
INT: 4
LONG: 4
DOUBLE: 8
1 Like

@timolol Yes calling stop() and begin() is neater if you are in control of the communications. However if your Spark is to be a UDP server it has to have communications awake all the time to pick up any incoming requests. That is why the code stops and restarts every 50 seconds. But you are quite right it is untidy. On the plus side I’ve had a server up an running for days on end with no hiccoughs.

1 Like

The more recent fixes (2/28 ish) will keep the sockets open (no more 60 sec timeout as stated above), unless there is a network issue and the cc3000 is reset. (cfod will cause this reset) So the being/stop will still help. We are going to have a notion of re-init of user objects to make this transparent for both UDP/TCP server/client communication.

2 Likes