Go Down

Topic: Is iOS causing WiFi server to crash? Some speculations with numbers. (Read 10232 times) previous topic - next topic

liuzengqiang

I have narrowed down a problem to the server.available() call. I have a skeletal program that is not much different from arduino sample code:

This code will tick at one second interval to indicate it is still running by printing out a character to Serial. It will also time a call to server.available() every 10 second so it won't swamp the serial port with too many printouts. Now the interesting stuff (latest firmware and library):

When the server is acting normally, the time spent with the server.available() call lasts 1-2 milliseconds (could be rounding error of millis).
When the server is about to crash or no longer responds to client connection, the time spent with the server.available() call lasts about 25ms, indicating some sort of timer expired?! After this, every call to this function lasts this long and the Arduino code still runs (with the second ticking) but will not find any client anymore. A restart is needed.

So what could be causing this problem?

Code: [Select]
#include <WiFi.h>
WiFiServer server(80);
unsigned long refresher1;
int status = WL_IDLE_STATUS;
char ssid[] = "";      //  my network SSID
char pass[] = "";   // won't tell everybody my password
int counter=0;
void setup()
{
  //Initialize serial and wait for port to open:
  Serial.begin(115200);
  delay(2000);
  unsigned long start=millis();
  while (WiFi.status() == WL_NO_SHIELD)
  {
    if ((millis()-start)>30000)
    {
      Serial.println(F("WiFi shield not present"));
      // don't continue:
      while(true);
    }
    delay(500);
  }
 
  while ( status != WL_CONNECTED) {
    Serial.print(F("Attempting to connect to SSID: "));
    Serial.println(ssid);
    status = WiFi.begin(ssid, pass);
    delay(10000);
  }
  server.begin();
  printWifiStatus();

  refresher1=millis();
}
void loop()
{
  int i=0;
  boolean check_time=false;
  if (millis()-refresher1>1000) // Ticks away
  {
    Serial.print("-");
    refresher1=millis();
    counter++;
    if (counter>=10)
    {
      counter=0;
      check_time=true;
      Serial.println();
      //Serial.print("Free memory=");
      //Serial.println(freeMemory());
    }
  }

  unsigned long t1=millis();
  // listen for incoming clients
  WiFiClient client = server.available();
  if (check_time)
  {
    Serial.print(F("Time in server.available():"));
    Serial.println(millis()-t1);
  }
 
  if (client)
  {
    unsigned long client_connected_timer=millis();
    Serial.println(F("\r\nNew client"));
    // an http request ends with a blank line
    boolean currentLineIsBlank = true;
    while ((WiFi.status() == WL_CONNECTED)&&client.connected()&&(millis()-client_connected_timer<2000))
    {
      if (client.available())
      {
        char c = client.read();
        Serial.write(c);
        if (c == '\n' && currentLineIsBlank)
        {
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");
          client.println("Connnection: close");
          client.println();
          client.println("<html>Just a test</html>");
          client.println();
          break;
        }
        if (c == '\n')
        {
          // you're starting a new line
          currentLineIsBlank = true;
        }
        else if (c != '\r')
        {
          // you've gotten a character on the current line
          currentLineIsBlank = false;
        }
      }
    }
    // give the web browser time to receive the data
    delay(25);
    client.flush(); // Make sure nothing is left when client disconnects.
    // close the connection:
    client.stop();
    delay(25);
    Serial.println(F("client disconnected"));
  }
}
void printWifiStatus() {
  // print the SSID of the network you're attached to:
  Serial.print(F("SSID: "));
  Serial.println(WiFi.SSID());

  // print your WiFi shield's IP address:
  IPAddress ip = WiFi.localIP();
  Serial.print(F("IP Address: "));
  Serial.println(ip);

  // print the received signal strength:
  long rssi = WiFi.RSSI();
  Serial.print(F("signal strength (RSSI):"));
  Serial.print(rssi);
  Serial.println(F(" dBm"));
}


Here is a log:

First there is no client, 1 ms spent looking for connected client. Then I used chrome browser twice, after that still looks for more client, spending 1 ms in the call.
Then I tried firefox twice, same result. I then tried ipad 2, it spits out a lot of meaningless requests for its icons (can't imagine how much internet servers hate ipads cause of these meaningless traffic), and then after that the call to server.available() became 25 ms long and arduino still ticks away but won't find any clients even when I tried all 3 browsers (so the loading never gets anything back).

Why is iOS making the server crash? I didn't have any of my code, just sample code with a few more sentences.
Code: [Select]
Time in server.available():1
----------
Time in server.available():1
----------
Time in server.available():1
-
New client
GET / HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Referer: http://192.168.1.5/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

client disconnected

New client
GET / HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

client disconnected
-
New client
GET / HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Referer: http://192.168.1.5/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

client disconnected
-
New client
GET / HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

client disconnected
--
New client
client disconnected
-----
Time in server.available():1
----------
Time in server.available():1
---
New client
GET / HTTP/1.1
Host: 192.168.1.5
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.5/
Connection: keep-alive
Cache-Control: max-age=0

client disconnected
----
New client
GET / HTTP/1.1
Host: 192.168.1.5
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64; rv:20.0) Gecko/20100101 Firefox/20.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://192.168.1.5/
Connection: keep-alive
Cache-Control: max-age=0

client disconnected
---
Time in server.available():1
----------
Time in server.available():1
-------
New client
GET / HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept-Encoding: gzip, deflate
User-Agent: Mozilla/5.0 (iPad; CPU OS 6_1_3 like Mac OS X) AppleWebKit/536.26 (KHTML, like Gecko) Version/6.0 Mobile/10B329 Safari/8536.25
Accept-Language: zh-cn
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8

client disconnected

New client
GET /apple-touch-icon-72x72-precomposed.png HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept-Encoding: gzip, deflate
User-Agent: MobileSafari/8536.25 CFNetwork/609.1.4 Darwin/13.0.0
Accept-Language: zh-cn
Accept: */*

client disconnected

New client
GET /apple-touch-icon-72x72.png HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept-Encoding: gzip, deflate
User-Agent: MobileSafari/8536.25 CFNetwork/609.1.4 Darwin/13.0.0
Accept-Language: zh-cn
Accept: */*

client disconnected
-
New client
GET /apple-touch-icon-precomposed.png HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept-Encoding: gzip, deflate
User-Agent: MobileSafari/8536.25 CFNetwork/609.1.4 Darwin/13.0.0
Accept-Language: zh-cn
Accept: */*

client disconnected

New client
GET /apple-touch-icon.png HTTP/1.1
Host: 192.168.1.5
Connection: keep-alive
Accept-Encoding: gzip, deflate
User-Agent: MobileSafari/8536.25 CFNetwork/609.1.4 Darwin/13.0.0
Accept-Language: zh-cn
Accept: */*

client disconnected
--
Time in server.available():1
----------
Time in server.available():1
----------
Time in server.available():25
----------
Time in server.available():25
----------
Time in server.available():26
----------
Time in server.available():25
--
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

liuzengqiang

I just tried every other browser including IE, chrome, firefox, tried quicktime, also android phone firefox. It was a lot of page refreshes and nothing went wrong. The server.available() while the server is idle is around 1 ms. Then I did one more with iphone 5, same thing happened as ipad2. The call to server.available() grew to 25ms each time and after that none can connect to the server.

This sample code is very simple and behavior is very persistent. So what is going on between iOS and Arduino WiFi shield? I'll get my Samsung Galaxy Tab II out for another round of test soon.

On a detailed look, the iOS HTTP request header is not particularly long (IE is longest), each line is not particular long (again IE sends longest line of request) so I don't think it is overrunning any buffers. I am not parsing the headers but just echoing on serial so they should have no effect other than size in wifi chip.
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

liuzengqiang

More clues:

I added a simple if statement to restart server with server.begin() if the delay to call server.available() goes beyond 10ms. What happens is very disappointing. The server may have failed to restart (remember the time none of arduino library that has begin() has end()?). Then each subsequent restart adds more delay to the server.available() call time until it hits 100 ms. Still no way to connect to it once it becomes this state.

Code: [Select]
Time in server.available():0
----------
Time in server.available():0
----------
Time in server.available():25
Restarting server.
----------
Time in server.available():49
Restarting server.
----------
Time in server.available():75
Restarting server.
----------
Time in server.available():99
Restarting server.
----------
Time in server.available():98
Restarting server.
----------
Time in server.available():100
Restarting server.
----------
Time in server.available():99
Restarting server.
----------
Time in server.available():99
Restarting server.
----------
Time in server.available():100
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

liuzengqiang

Also adding client.stop() before restarting server with server.begin() won't help either. I wish this shield has a separate reset pin instead of tied to arduino. What if I want to reset the shield without resetting Arduino, cutting some pins?
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

liuzengqiang

I don't know what really changed between the stock firmware in wifi shield R3 and the "latest" firmware. Same can be said about the arduino wifi library. Anyway. I reverted to the original wifi shield R3 since I have one other shield that I didn't upgrade firmware. I had to remove the latest arduino wifi library and revert to a previous version (again unable to mention version numbers cause there is NONE!). Now the iOS works nicely. I can repeatedly load web pages and there is no extra delay calling the server.available() anymore.

Whatever the firmware dev guy did, didn't solve a few problems I had and only created more.

Remember (to self mostly since nobody has replied so far) that when I said TWO chrome loads but actual log I posted has 4 logs from chrome all asking for "/"? How weird?

Now with the original R3 and older library, the two duplicate GET from chrome turned out to be first "/" then"/favicon.ico".

Code: [Select]
ew client
GET / HTTP/1.1
Host: 192.168.1.14
Connection: keep-alive
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

client disconnected
--
New client
GET /favicon.ico HTTP/1.1
Host: 192.168.1.14
Connection: keep-alive
Accept: */*
User-Agent: Mozilla/5.0 (Windows NT 6.0; WOW64) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.64 Safari/537.31
Accept-Encoding: gzip,deflate,sdch
Accept-Language: en-US,en;q=0.8
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

client disconnected
-------
Time in server.available():0
----------
Time in server.available():0
----


Something is definitely wrong with current version of firmware and library!!!
Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

sonnyyu

You did 5 posts alone, did you feel lonely?
I wish I have straight answer but I do not have Arduino wifi shield, for $90.00 I manage to get Pi with wifi, wimax, 4G LTE, bluetooth Arduino shield together. However I would like to recommend some method might help;-

1. Package sniffer, Wireshark  802.11 Packet Capture. use it Capture Packet  form PC browser and Ipad browser to see the difference.
2. HTTP proxy server, use proxy server to proxy request and log it.
iPad HTTP Debugging with Charles



liuzengqiang


You did 5 posts alone, did you feel lonely?
I wish I have straight answer but I do not have Arduino wifi shield, for $90.00 I manage to get Pi with wifi, wimax, 4G LTE, bluetooth Arduino shield together. However I would like to recommend some method might help;-

1. Package sniffer, Wireshark  802.11 Packet Capture. use it Capture Packet  form PC browser and Ipad browser to see the difference.
2. HTTP proxy server, use proxy server to proxy request and log it.
iPad HTTP Debugging with Charles

Well, what about you? I tend to post my progress and conclusion.

You certainly can get all your pi stuff for under $90 but you probably don't have a large working project built around arduino already and needs to grow wireless capabilities. I need to use arduino. If I start a new projct I might give pi a slight consideration. The pi sounds to me like it focuses on running OS and software on a small card, with a few io pins. Its complexity seems overkill to what I do. I don't have time to learn linux system for projects that mostly deals with data collection and calculations.

I will give the wireshark a try. At least to find out the difference between ios and other systems and how that might screw up the arduino wifi shield.

Serial LCD keypad panel,phi_prompt user interface library,SDI-12 USB Adapter

Riva

Not much help to you but my iPhone running IOS5 used to crash the Wi-Fi on my router. Cable connections would continue to work fine but I could get nothing to connect using Wi-Fi and the routers web interface would not load to try any debugging/restarts. Only option was to power cycle the router. Thankfully this has not happened since updating to IOS6.
My view of IOS is 'looks pretty, works quite well but very simplistic (basic) functionality)
Don't PM me for help as I will ignore it.

Go Up