title: How many simultaneous/consecutive connections can an ESP8266 Webserver handle?
body: <p>So I'm using the <strong>ESP8266WebServer</strong> and <strong>ESP8266WiFiMulti</strong> libraries to run a webpage with <strong>websockets</strong> and I'm trying to figure out how many client connections I can have, and if there's any way to increase that connection limit? </p>
  
  <p>Right now it seems that I can successfully create <strong>three</strong> connections from <strong>separate IPs</strong>, and then upon initiating the <strong>fourth</strong> connection, it fails (the server doesn't crash in the serial model, but the fourth connection won't load the webpage). </p>
  
  <p>I've also noticed that if I refresh my own <strong>singular</strong> connection a certain number of times <strong>(inconsistent)</strong>, it will fail to load the webpage as well. I haven't been able to decipher whether this has to do with there being <strong>too many consecutive connections</strong> in general or if I'm <strong>overtaxing the server</strong> by attempting to reconnect within too quick a timeframe?</p>
  
  <p>In general though, it seems rather <strong>unstable</strong> and I could really use some assistance on figuring out why. </p>
  
  <p>Here's my current code: </p>
  
  <pre><code>#include &lt;ESP8266WiFi.h&gt;
  #include &lt;ESP8266WiFiMulti.h&gt;
  #include &lt;WebSocketsServer.h&gt;
  #include &lt;Hash.h&gt;
  #include &lt;ESP8266WebServer.h&gt;
  #include &lt;ESP8266mDNS.h&gt;
  
  static const char ssid[] = "********";
  static const char password[] = "********";
  MDNSResponder mdns;
  
  static void writeLED(bool);
  
  ESP8266WiFiMulti WiFiMulti;
  
  IPAddress ipAddressTest = (99,99,99,99);
  
  ESP8266WebServer server(80);
  WebSocketsServer webSocket = WebSocketsServer(81);
  
  uint8_t pageHitCounter = 0;
  IPAddress ipAddressOne = (99,99,99,99); 
  IPAddress ipAddressTwo = (99,99,99,99); 
  IPAddress ipAddressThree = (99,99,99,99); 
  IPAddress ipAddressFour = (99,99,99,99); 
  
  uint8_t rxBuff[256];
  uint8_t som = 0x11; 
  uint8_t eom = 0x12; 
  uint8_t subsys; 
  uint8_t receivedSubsys;
  uint8_t rx_byte = 0x00;
  uint8_t messageLength = 0;
  uint8_t receivedMessageLength = 0;
  uint8_t messageContent;
  uint8_t serialCurrent; 
  
  int initialCounter = 0;
  boolean messageBegun = false; 
  boolean messageInProgress = false;
  
  int currNumRefresh = 0;
  int currMicroC = 0;
  int currMicroD = 0;
  int currMicroE = 0;
  int currPressureC = 0; 
  int currPressureD = 0; 
  int currPressureE = 0; 
  int currValveStatusNumC = 0; 
  int currValveStatusNumD = 0; 
  int currValveStatusNumE = 0;
  int currFluid = 0;
  
  char statusbuf[256]; 
  char status[] = "";
  int statusIndex = 0;
  
  String valveStatusC = "Closed";
  String valveTubePropsC = "175px solid #00ADEF";
  String valveColorC = "red";
  
  String valveStatusD = "Closed";
  String valveTubePropsD = "175px solid #00ADEF";
  String valveColorD = "red";
  
  String valveStatusE = "Closed";
  String valveTubePropsE = "175px solid #00ADEF";
  String valveColorE = "red";
  
  uint8_t currCountdown = 0;
  long prevTimeCountdown = 0; 
  long countdownInterval = 1000; 
  long countdownPostInterval = 100;
  bool countdownFlag = true;
  
  bool teensyPOWER = false;
  bool pumpPOWER = false;
  bool teensyLED = false;
  
  void switchPOWERon() {
  
  //Serial.println("TEST POWER ON");
  
  int powerStatusLength = 1;
  
  subsys = 0x10; 
  
  //Account for the end of message
  messageLength = powerStatusLength + 2;
  
  messageContent = 1;
  
  Serial.write(som);
  Serial.write(messageLength);
  Serial.write(subsys);
  Serial.write(messageContent);
  Serial.write(eom);
  //Serial.println("");
  //Serial.println("TURN POWER ON|");
  //teensyLED = true;
  } //end switchPOWERon
  
  void switchPOWERoff() {
  /*Very similar to switchPoweron(), removed for char space*/
  } //end switchPOWERoff
  
  void pumpPOWERon() {
  
  //Serial.println("TEST POWER ON");
  
  int pumpPowerStatusLength = 1;
  
  subsys = 0x13; 
  
  //Account for the end of message
  messageLength = pumpPowerStatusLength + 2;
  
  messageContent = 1;
  
  Serial.write(som);
  Serial.write(messageLength);
  Serial.write(subsys);
  Serial.write(messageContent);
  Serial.write(eom);
  //Serial.println("");
  //Serial.println("TURN POWER ON|");
  //teensyLED = true;
  } //end switchPOWERon
  
  void pumpPOWERoff() {
  
  /*Very similar to pumpPoweron(), removed for char space*/
  } //end switchPOWERoff
  
  void switchLEDon() {
  
  //Serial.println("TEST LED ON");
  
  int ledStatusLength = 1;
  
  subsys = 0x14; 
  
  //Account for the end of message
  messageLength = ledStatusLength + 2;
  
  messageContent = 1;
  
  Serial.write(som);
  Serial.write(messageLength);
  Serial.write(subsys);
  Serial.write(messageContent);
  Serial.write(eom);
  //Serial.println("");
  //Serial.println("TURN LED ON|");
  //teensyLED = true;
  } //end switchLEDon
  
  void switchLEDoff() {
  
  /*Very similar to switchLEDon(), removed for char space*/
  } //end switchLEDoff
  
  void statusUpdate(uint8_t num) {
  
  //Valve C
  if(currValveStatusNumC == 0)
  {
      valveColorC = "red";
      valveTubePropsC = "175px solid #00ADEF";
      valveStatusC = "Closed";
  } //end if
  else if(currValveStatusNumC == 1)
  {
      valveColorC = "green";
      valveTubePropsC = "350px solid #00ADEF"; 
      valveStatusC = "Open";
  } //end else if
  
  /*Valves D/E removed for char space, very similar to Valve C*/
  
  String test = ""; 
  test += currNumRefresh;
  test += ",";
  /*Preparing more variables to send to the webpage, removed for char space*/
  test += ",";
  test += ipAddressTest;
  
  //Serial.print("TEST: ");
  //Serial.println(ipAddressTest);
  
  test.toCharArray(statusbuf, 256);
  webSocket.sendTXT(num, statusbuf, strlen(statusbuf));
  }
  
  static const char PROGMEM INDEX_HTML[] = R"rawliteral(
  &lt;!DOCTYPE html&gt; 
  &lt;html&gt;
  &lt;head&gt;
      &lt;title&gt;Adafruit HUZZAH ESP8266&lt;/title&gt;
  
  &lt;style type='text/css'&gt;   
  /*CSS removed to fit maximum number of allowed characters*/
  &lt;/style&gt;
  &lt;script&gt;
  
  var currPressureTest = 0;
  var currFluidTest = 0;                                               
  
  function POWERswitch(){
  var POWERswitchCheck = document.getElementById('switch1').checked;        
  
  if(POWERswitchCheck){
      websock.send("teensyPOWERon");      
  }
  else if(!POWERswitchCheck) {
      websock.send("teensyPOWERoff");
  }
  }
  
  function FLUSHbegin(){
  websock.send("pumpPOWERon");            
  }
  
  function FLUSHend(){
  websock.send("pumpPOWERoff");
  }
  
  function LEDswitch(){
  var LEDswitchCheck = document.getElementById('myonoffswitch').checked;        
  
  if(LEDswitchCheck){
      websock.send("teensyLEDon");      
  }
  else if(!LEDswitchCheck) {
      websock.send("teensyLEDoff");
  }
  }
  
  var websock;
  var test = "open";
  var webpageHitCounter = 20; 
  
  function start() {
  websock = new WebSocket('ws://' + window.location.hostname + ':81/');
  websock.onopen = function(evt) { 
      console.log('websock open'); 
      statusUpdate();
  };
  websock.onclose = function(evt) { 
      console.log('websock close'); 
  };
  websock.onerror = function(evt) { 
      console.log(evt); 
  };
  websock.onmessage = function(evt) {
      console.log(evt);
      var e = document.getElementById('ledstatus');
      var te = document.getElementById('myonoffswitch');
      var pe = document.getElementById('switch1');
  
  
      if(evt.data === 'teensyPOWERon')
      {
          pe.checked = 'checked';
      }
      else if(evt.data === 'teensyPOWERoff')
      {
          pe.checked = '';
      }
      else if(evt.data === 'pumpPOWERon')
      {
  
      }
      else if(evt.data === 'pumpPOWERoff')
      {
  
      }
      else if(evt.data === 'teensyLEDon')
      {
          te.checked = 'checked';
      }
      else if(evt.data === 'teensyLEDoff')
      {
          te.checked = '';
      }
      else if(evt.data === 'Update Status')
      {
  
      }
      else {
        console.log('status event');
  
        var totalStatus = evt.data;                                              
        var splitStatus = totalStatus.split(',');                                                                                     
  
        //Num Refresh
        document.getElementById("demo").innerHTML = splitStatus[0];                 
  
        /*Setting more variables from splitStatus[], removed for char space*/
  
        }
    };
    }
  
    function statusUpdate() {
    websock.send("Update Status");
    setTimeout('statusUpdate()', 5000);  
    }
  
      &lt;/script&gt;                  
  &lt;/head&gt;
  
  &lt;body style='background-color:#4a4a4c;' onload="start();"&gt;
  
      &lt;div style='text-align:center;'&gt;
          &lt;h1 style='text-decoration: underline; color:white;'&gt;Adafruit HUZZAH ESP8266&lt;/h1&gt;
      &lt;/div&gt;
  
      &lt;meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes"&gt;
  
      &lt;div style="clear:both;"&gt;&lt;/div&gt;     
  
      &lt;div class='counterContainer'&gt;
          &lt;span id="counterText" style="color:white;"&gt;&lt;/span&gt;
      &lt;/div&gt;
  
      &lt;div id='adminControls' class='adminControlsRow'&gt;
  
          &lt;h2&gt;Administrator Controls&lt;/h2&gt;
  
          &lt;div id='Newbtn' class='powerSwitchContainer'&gt;
              &lt;h2&gt;HHIO PTT Power&lt;/h2&gt;
  
              &lt;span class="switch"&gt;
                 &lt;span class="switch-border1"&gt;
                      &lt;span class="switch-border2"&gt;
                         &lt;input id="switch1" type="checkbox" onclick='POWERswitch()' checked /&gt;
                         &lt;label for="switch1"&gt;&lt;/label&gt;
                         &lt;span class="switch-top"&gt;&lt;/span&gt;
                         &lt;span class="switch-shadow"&gt;&lt;/span&gt;
                         &lt;span class="switch-handle"&gt;&lt;/span&gt;
                         &lt;span class="switch-handle-left"&gt;&lt;/span&gt;
                         &lt;span class="switch-handle-right"&gt;&lt;/span&gt;
                         &lt;span class="switch-handle-top"&gt;&lt;/span&gt;
                         &lt;span class="switch-handle-bottom"&gt;&lt;/span&gt;
                         &lt;span class="switch-handle-base"&gt;&lt;/span&gt;
                         &lt;span class="switch-led switch-led-green"&gt;
                            &lt;span class="switch-led-border"&gt;
                               &lt;span class="switch-led-light"&gt;
                                  &lt;span class="switch-led-glow"&gt;&lt;/span&gt;
                               &lt;/span&gt;
                            &lt;/span&gt;
                         &lt;/span&gt;
                         &lt;span class="switch-led switch-led-red"&gt;
                            &lt;span class="switch-led-border"&gt;
                              &lt;span class="switch-led-light"&gt;
                                  &lt;span class="switch-led-glow"&gt;&lt;/span&gt;
                               &lt;/span&gt;
                            &lt;/span&gt;
                         &lt;/span&gt;
                      &lt;/span&gt;
                 &lt;/span&gt;
              &lt;/span&gt;
          &lt;/div&gt;
          &lt;div class='flushBtnContainer'&gt;
              &lt;h2&gt;Fluid Reservoir&lt;/h2&gt;
              &lt;button id='flushBtn' onmousedown="FLUSHbegin();" onmouseup="FLUSHend();"&gt;Flush&lt;/button&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;div style='background-color:#1E1E20; clear:both;'&gt;
          &lt;h2 style='color: white;'&gt;LED Controls&lt;/h2&gt;                            
          &lt;div id='LEDbtn' class='onoffswitch'&gt;                             
              &lt;input type='checkbox' name='onoffswitch' class='onoffswitch-checkbox' id='myonoffswitch' onclick='LEDswitch()'&gt;                            
              &lt;label class='onoffswitch-label' for='myonoffswitch'&gt;
                  &lt;span class='onoffswitch-inner'&gt;&lt;/span&gt;
                  &lt;span class='onoffswitch-switch'&gt;&lt;/span&gt;
              &lt;/label&gt;
          &lt;/div&gt;
      &lt;/div&gt;              
  
      &lt;div style='background-color:#1E1E20; color: white;'&gt;
          &lt;h2&gt;Num Refresh Test&lt;/h2&gt;    
          &lt;div id="demo"&gt;&lt;h2&gt;Let WEBSOCKET change this text&lt;/h2&gt;&lt;/div&gt;
      &lt;/div&gt;
  
      &lt;div class='headerRow'&gt;
          /*Headers removed for char space*/
      &lt;/div&gt;
  
      &lt;div class='microswitchRow'&gt;
          &lt;div class="microswitchContainer"&gt;
            &lt;div class="microswitch white"&gt;
               &lt;input type="radio" name="switchC" class="microswitchRadio" id="switchOffC" checked&gt;
               &lt;input type="radio" name="switchC" class="microswitchRadio" id="switchOnC"&gt;
  
               &lt;label for="switchOffC"&gt;Detached&lt;/label&gt;
               &lt;label for="switchOnC"&gt;Attached&lt;/label&gt;
  
               &lt;span class="toggle"&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="microswitchContainer"&gt;
            &lt;div class="microswitch white"&gt;
               &lt;input type="radio" name="switchD" class="microswitchRadio" id="switchOffD" checked&gt;
               &lt;input type="radio" name="switchD" class="microswitchRadio" id="switchOnD"&gt;
  
               &lt;label for="switchOffD"&gt;Detached&lt;/label&gt;
               &lt;label for="switchOnD"&gt;Attached&lt;/label&gt;
  
               &lt;span class="toggle"&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/div&gt;
          &lt;div class="microswitchContainer"&gt;
            &lt;div class="microswitch white"&gt;
               &lt;input type="radio" name="switchE" class="microswitchRadio" id="switchOffE" checked&gt;
               &lt;input type="radio" name="switchE" class="microswitchRadio" id="switchOnE"&gt;
  
               &lt;label for="switchOffE"&gt;Detached&lt;/label&gt;
               &lt;label for="switchOnE"&gt;Attached&lt;/label&gt;
  
               &lt;span class="toggle"&gt;&lt;/span&gt;
            &lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;div class='pressureRow'&gt;
          &lt;div class='pressureContainer'&gt;
              &lt;div class='gauge-a'&gt;&lt;/div&gt;
              &lt;div class='gauge-b'&gt;&lt;/div&gt;
              &lt;div class='gauge-c'&gt;&lt;/div&gt;
              &lt;div class='gauge-data'&gt;&lt;h1 id='pressurePercentC'&gt;0%&lt;/h1&gt;&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class='pressureContainer'&gt;
              &lt;div class='gauge-a'&gt;&lt;/div&gt;
              &lt;div class='gauge-b'&gt;&lt;/div&gt;
              &lt;div class='gauge-d'&gt;&lt;/div&gt;
              &lt;div class='gauge-data'&gt;&lt;h1 id='pressurePercentD'&gt;0%&lt;/h1&gt;&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class='pressureContainer'&gt;
              &lt;div class='gauge-a'&gt;&lt;/div&gt;
              &lt;div class='gauge-b'&gt;&lt;/div&gt;
              &lt;div class='gauge-e'&gt;&lt;/div&gt;
              &lt;div class='gauge-data'&gt;&lt;h1 id='pressurePercentE'&gt;0%&lt;/h1&gt;&lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;           
  
      &lt;div class='valveRow'&gt;
          &lt;div class='valveContainer'&gt;
              &lt;div class="valveTube-c"&gt;&lt;/div&gt;
              &lt;div class="valve-c"&gt;&lt;/div&gt;
              &lt;div class='valve-data'&gt;&lt;h1 id='valveStatus-c'&gt;Closed&lt;/h1&gt;&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class='valveContainer'&gt;
              &lt;div class="valveTube-d"&gt;&lt;/div&gt;
              &lt;div class="valve-d"&gt;&lt;/div&gt;
              &lt;div class='valve-data'&gt;&lt;h1 id='valveStatus-d'&gt;Closed&lt;/h1&gt;&lt;/div&gt;
          &lt;/div&gt;
          &lt;div class='valveContainer'&gt;
              &lt;div class="valveTube-e"&gt;&lt;/div&gt;
              &lt;div class="valve-e"&gt;&lt;/div&gt;
              &lt;div class='valve-data'&gt;&lt;h1 id='valveStatus-e'&gt;Closed&lt;/h1&gt;&lt;/div&gt;
          &lt;/div&gt;
      &lt;/div&gt;
  
      &lt;div class='fluidContainer'&gt;
          &lt;meter class='fluidMeter' max='100' value='50' low='25' high='75' optimum='100'&gt;&lt;/meter&gt; 
          &lt;div class='fluid-data'&gt;&lt;h1 id='fluidPercent'&gt;0%&lt;/h1&gt;&lt;/div&gt;
      &lt;/div&gt;
  
      &lt;/body&gt;
  &lt;/html&gt;
  )rawliteral";
  
  const int LEDPIN = 0;
  
  // Current POWER status
  bool POWERStatus;
  
  // Current LED status
  bool LEDStatus;
  
  // Commands sent through Web Socket
  /*command array declarations removed for char space*/
  
  const char statusIdentifier[] = "Update Status";
  
  void webSocketEvent(uint8_t num, WStype_t type, uint8_t * payload, size_t length)
  {
    //Serial.printf("webSocketEvent(%d, %d, ...)\r\n", num, type);
    switch(type) {
      case WStype_DISCONNECTED:
    //Serial.printf("[%u] Disconnected!\r\n", num);
    break;
      case WStype_CONNECTED:
    {
      IPAddress ip = webSocket.remoteIP(num);
      //Serial.printf("[%u] Connected from %d.%d.%d.%d url: %s\r\n", num, ip[0], ip[1], ip[2], ip[3], payload);
  
      // Send the current LED status
      if (LEDStatus) {
        webSocket.sendTXT(num, LEDON, strlen(LEDON));
      }
      else if(!LEDStatus) {
        webSocket.sendTXT(num, LEDOFF, strlen(LEDOFF));
      }
      else if(teensyPOWER) {
        webSocket.sendTXT(num, teensyPOWERON, strlen(teensyPOWERON));
      }
      else if(!teensyPOWER) {
        webSocket.sendTXT(num, teensyPOWEROFF, strlen(teensyPOWEROFF));
      }  
      else if(pumpPOWER) {
        webSocket.sendTXT(num, teensyPOWERON, strlen(teensyPOWERON));
      }
      else if(!pumpPOWER) {
        webSocket.sendTXT(num, pumpPOWEROFF, strlen(pumpPOWEROFF));
      }  
      else if(teensyLED) {
        webSocket.sendTXT(num, teensyLEDON, strlen(teensyLEDON));
      }
      else if(!teensyLED) {
        webSocket.sendTXT(num, teensyLEDOFF, strlen(teensyLEDOFF));
      }
    }
    break;
  case WStype_TEXT:
    //Serial.printf("[%u] get Text: %s\r\n", num, payload);
  
    if (strcmp(LEDON, (const char *)payload) == 0) {
      writeLED(true);
    }
    else if (strcmp(LEDOFF, (const char *)payload) == 0) {
      writeLED(false);
    }
    else if(strcmp(teensyPOWERON,  (const char *)payload) == 0) {
        switchPOWERon();
    }
    else if(strcmp(teensyPOWEROFF,  (const char *)payload) == 0) {
        switchPOWERoff();
    }
    else if(strcmp(pumpPOWERON,  (const char *)payload) == 0) {
        pumpPOWERon();
    }
    else if(strcmp(pumpPOWEROFF,  (const char *)payload) == 0) {
        pumpPOWERoff();
    } 
    else if(strcmp(teensyLEDON,  (const char *)payload) == 0) {
        switchLEDon();
    }
    else if(strcmp(teensyLEDOFF,  (const char *)payload) == 0) {
        switchLEDoff();
    }
    else if(strcmp(statusIdentifier, (const char *)payload) == 0) {
        statusUpdate(num);
    }
    else {
      //Serial.println("Unknown command");
    }
    // send data to all connected clients
    webSocket.broadcastTXT(payload, length);
    break;
  case WStype_BIN:
    //Serial.printf("[%u] get binary length: %u\r\n", num, length);
    hexdump(payload, length);
  
    // echo data back to browser
    webSocket.sendBIN(num, payload, length);
    break;
  default:
    //Serial.printf("Invalid WStype [%d]\r\n", type);
    break;
    }
  }
  
  void handleRoot()
  {
  
    server.send(200, "text/html", INDEX_HTML);
  
    if(ipAddressTest != (0,0,0,0))
    {
    if(ipAddressOne == (99,99,99,99))
    {
        ipAddressOne = ipAddressTest;
        pageHitCounter++;
        //server.send(200, "text/html", INDEX_HTML);
  
        Serial.print("1st NEW IP: ");
        Serial.println(ipAddressTest);
        }
  
        else if(ipAddressTwo == (99,99,99,99))
        {
        if(ipAddressOne == ipAddressTest)
        {
            Serial.print("Old Connection-1 currently connected; Current Connection: ");
            Serial.println(ipAddressTest);
            //server.send(200, "text/html", INDEX_HTML);
        }
        else
        {
            ipAddressTwo = ipAddressTest;
            pageHitCounter++;
            //server.send(200, "text/html", INDEX_HTML);
  
            Serial.print("2nd NEW IP: ");
            Serial.println(ipAddressTest);
        }
        }
  
        else if(ipAddressThree == (99,99,99,99)) 
        {
        if(ipAddressOne == ipAddressTest || ipAddressTwo == ipAddressTest)
        {
             Serial.print("Old Connection-2 currently connected; Current Connection: ");
             Serial.println(ipAddressTest);
             //server.send(200, "text/html", INDEX_HTML);
        }
        else
        {
            ipAddressThree = ipAddressTest;
            pageHitCounter++;
            //server.send(200, "text/html", INDEX_HTML);
  
            Serial.print("3rd NEW IP: ");
            Serial.println(ipAddressTest);
        }
        }
  
        else if(ipAddressFour == (99,99,99,99))
        {
        if(ipAddressOne == ipAddressTest || ipAddressTwo == ipAddressTest || ipAddressThree == ipAddressTest)
        {
             Serial.println("Old Connection-3 currently connected; Current Connection: ");
             Serial.println(ipAddressTest);
             //server.send(200, "text/html", INDEX_HTML);
        }
        else
        {
            ipAddressFour = ipAddressTest;
            pageHitCounter++;
            //server.send(200, "text/html", INDEX_HTML);
  
            Serial.print("4th NEW IP: ");
            Serial.println(ipAddressTest);
        }
        }
  
        else
        {
        if(ipAddressOne == ipAddressTest || ipAddressTwo == ipAddressTest || ipAddressThree == ipAddressTest || ipAddressFour == ipAddressTest)
        {
             Serial.println("Old Connection-4 currently connected; Current Connection: ");
             Serial.println(ipAddressTest);
             //server.send(200, "text/html", INDEX_HTML);
        }
        else
        {
            Serial.print("Too many connections! Attempting to Connect: ");
            Serial.println(ipAddressTest);
        }
        }
    }
  
  
  
  }
  
  void handleNotFound()
  {
    String message = "File Not Found\n\n";
    message += "URI: ";
    message += server.uri();
    message += "\nMethod: ";
    message += (server.method() == HTTP_GET)?"GET":"POST";
    message += "\nArguments: ";
    message += server.args();
    message += "\n";
    for (uint8_t i=0; i&lt;server.args(); i++){
      message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
    }
    server.send(404, "text/plain", message);
  }
  
  static void writeLED(bool LEDon)
  {
    LEDStatus = LEDon;
    // Note inverted logic for Adafruit HUZZAH board
    if (LEDon) {
      digitalWrite(LEDPIN, 0);
    }
    else {
      digitalWrite(LEDPIN, 1);
    }
  }
  
  void setup()
  {
    pinMode(LEDPIN, OUTPUT);
    writeLED(false);
  
    Serial.begin(115200);
  
    //Serial.setDebugOutput(true);
  
    Serial.println();
    Serial.println();
    Serial.println();
  
    currCountdown = 4; 
  
    for(uint8_t t = 4; t &gt; 0; t--) {
  
  unsigned long currTime = millis();
  
  if(countdownFlag == true)
  {
      Serial.printf("[SETUP] BOOT WAIT %d...\r\n", t);
      Serial.flush();
      countdownFlag = false; 
  }
  
  
  if(currTime - prevTimeCountdown &gt; countdownInterval)
  {
      prevTimeCountdown = currTime; 
      countdownFlag = true; 
  } //end if
  
  else
  {
      t++;
  } //end else
  
    } //end for
  
    WiFiMulti.addAP(ssid, password);
  /*
    prevTimeCountdown = 0;
    countdownFlag = true;
  */   
    while(WiFiMulti.run() != WL_CONNECTED) {
    /*
    unsigned long currTime = millis();
  
    if(countdownFlag == true)
    {
        Serial.print(".");
        countdownFlag = false; 
    } //end if
  
    if(currTime - prevTimeCountdown &gt; countdownInterval)
    {
        prevTimeCountdown = currTime; 
        countdownFlag = true; 
    } //end if
    */
    Serial.print(".");
    delay(1000);
  
    } //end while
  
    Serial.println("");
    Serial.print("Connected to ");
    Serial.println(ssid);
    Serial.print("IP address: ");
    Serial.println(WiFi.localIP());
  
    if (mdns.begin("espWebSock", WiFi.localIP())) {
      Serial.println("MDNS responder started");
      mdns.addService("http", "tcp", 80);
      mdns.addService("ws", "tcp", 81);
    }
    else {
      Serial.println("MDNS.begin failed");
    }
    Serial.print("Connect to http://espWebSock.local or http://");
    Serial.println(WiFi.localIP());
  
    server.on("/", handleRoot);
    server.onNotFound(handleNotFound);
  
    server.begin();
  
    webSocket.begin();
    webSocket.onEvent(webSocketEvent);
      }
  
  void loop()
  {
  //Communication Protocol
  if(Serial.available() &gt; 0)
  {
      //Serial.print("SERIAL.AVAILABLE: ");
      //Serial.println(Serial.available());
  
      if(initialCounter == 0)
      {
          rx_byte = Serial.read();
      /*
          //Print Start of Message
          Serial.print("0x");
          if(rx_byte&lt;0x10)
          {
              Serial.print("0");
          }
          Serial.println(rx_byte, HEX);
      */
          //Serial.println(rx_byte, BIN);
          //Serial.println(rx_byte);
  
          initialCounter++;
      }
  
  
      if((!messageBegun) &amp;&amp; (rx_byte == som))
      {
          messageBegun = true;
  
          //Serial.println("MESSAGE BEGUN TRUE");
      } //end if (messageInProgress &amp;&amp; rx_byte)
  
      if((messageBegun) &amp;&amp; (!messageInProgress))
      {
          serialCurrent = Serial.available();
  
          if(serialCurrent &gt; 0)
          {      
              receivedMessageLength = (uint8_t)Serial.read();
          /*
              Serial.print("MESSAGE LENGTH: ");
              Serial.println(receivedMessageLength);
          */
              messageBegun = false;
  
              messageInProgress = true;
  
              //Serial.println("MESSAGE IN PROGRESS TRUE");
  
          } //end if (serialCurrent)
      } //end if (messageBegun &amp;&amp; messageInProgress)
  
      if(messageInProgress)
      {
          serialCurrent = Serial.available(); 
  
          if(serialCurrent &gt;= receivedMessageLength)
          {
  
              Serial.readBytes(rxBuff, receivedMessageLength);
  
              if((byte)rxBuff[receivedMessageLength-1] != eom)
              {
                  //Serial.println("ERROR");
                  //Serial.write(Serial.read());
              } //end if (rxBuff != eom)
  
              else
              {
                  messageInProgress = false; 
  
                  for(int i=0; i&lt;receivedMessageLength; i++)
                  {
                      if(rxBuff[i] == eom)
                      {
                      /*
                          //Print End of Message
                          Serial.print("0x");
                          if(rx_byte&lt;0x10)
                          {
                              Serial.print("0");
                          }
                          Serial.println(rxBuff[i], HEX);
                      */
                          initialCounter = 0;
  
                          receivedMessageLength = 0;
  
                      } //end if
  
                      else if(i == 0)
                      {
                          receivedSubsys = rxBuff[i]; 
                      /*
                          //Print Subsystem
                          Serial.print("0x");
                          if(rx_byte&lt;0x10)
                          {
                              Serial.print("0");
                          }
                          Serial.println(rxBuff[i], HEX);
                      */
                      } //end if
                      else
                      {
                          if(receivedSubsys == 0x14)
                          {
                              currNumRefresh = rxBuff[i];
                          } //end if
  
                          /*Other subsystems removed for char space*/
              } //end else
  
          } //end if (serialCurrent)
  
      } //end if (messageInProgress)
  } //end if (Serial.available)
  
    webSocket.loop();
    ipAddressTest = server.handleClient();
  }
  </code></pre>
  
  <p>P.S. I slightly modified <strong>ESP8266WebServer.cpp's handleClient()</strong> function to return the current IP address in order to track individual users, however sometimes I get <strong>0.0.0.0</strong> as an IP address and I don't know why or how to tell if that IP is a new IP or not. </p>