Go Down

Topic: WiFi & Sockets (Read 643 times) previous topic - next topic

RayLivingston

2.4-rc2, which was handy, because I also needed the ability to set the max # of connections for softAP mode to 8.

Regards,
Ray L.

Juraj

and the connection stability is better?

RayLivingston

I actually didn't have connection problems with 2.2.0, once I started using higher numbered channels.  2.3.0 has TERRIBLE connection problems.  I switched to 2.4.0-rc2 to be able to increase the number of AP connections.  I do not understand why the channel number makes such a difference in reliability, given that the lower channel work very poorly even when there are NO other WiFi networks in the area (I live out in the sticks, so my network is the only one within about 500 feet or more.

Regards,
Ray L.

RayLivingston

#18
Dec 07, 2017, 06:38 pm Last Edit: Dec 07, 2017, 06:39 pm by RayLivingston
Hmmmm....  Seems I am now back to having connection problems....  I'm playing with different ways of communicating with a number of clients.  One approach is having everyone using a single port, talking to a single server.  That seems to work well, with good through-put, for some period, then the server eventually decides to stop responding most of the time.  One or two connections will get through, sporadically.  Another approach, in the code below, sets up multiple servers on that same port.  That works, surprisingly, MUCH worse - with MUCH slower response and throughput, and eventually ALL the servers stop responding.  I've also tried multiple servers on different ports, which each client having its own  port.  This also does not work particularly well.

Why do the servers stop responding?  I am currently doing a server.begin() after each connection closes, which seems to slightly improve reliability (the data flows a bit longer before the server stops responding), but also slows down the connection rate, so it's not really a help overall.

Regards,
Ray L.

Code: [Select]

#include <ESP8266WiFi.h>
extern "C" {
#include "user_interface.h"
}

#define SERVER
#define ECHO

#define NSOCKETS 6

#if defined(SERVER)
WiFiServer servers[NSOCKETS] = { WiFiServer(8000), WiFiServer(8000), WiFiServer(8000), WiFiServer(8000), WiFiServer(8000), WiFiServer(8000) };
uint32_t statusTime = 0;
#endif

WiFiClient clients[NSOCKETS] = { WiFiClient(), WiFiClient(), WiFiClient(), WiFiClient(), WiFiClient(), WiFiClient() };

IPAddress Netmask = IPAddress(255, 255, 255, 0);

char *STASSID = "TP-LINK_A47DC2";
char *STAPass = "79517515";
IPAddress STAGatewayIP = IPAddress(10, 0, 0, 1);
IPAddress STAIP = IPAddress(10, 0, 0, 50);

char *APSSID = "WiFiNetwork";
char *APPass = "WiFiPassword";
IPAddress APIP = IPAddress(192, 168, 0, 1);

IPAddress ClientIP = IPAddress(192, 168, 0, 2);
//IPAddress ClientIP = IPAddress(192, 168, 0, 3);
//IPAddress ClientIP = IPAddress(192, 168, 0, 4);
//IPAddress ClientIP = IPAddress(192, 168, 0, 5);
//IPAddress ClientIP = IPAddress(192, 168, 0, 6);


char s[80];
int i = 0;
uint32_t timer = 0;

#if defined(SERVER)
void ServerSetup()
{
boolean success = false;

while (!success)
{
// Disconnect, if connected
WiFi.disconnect();

// Set Mode
if (!(success = WiFi.mode(WiFiMode_t::WIFI_AP_STA)))
continue;

// Configure STA
if (!(success = WiFi.config(STAIP, STAGatewayIP, Netmask, STAGatewayIP)))
continue;

// Configure AP
if (!(success = WiFi.softAPConfig(APIP, STAGatewayIP, Netmask)))
continue;

// Start/Connect AP + STA
WiFi.persistent(true);
if (!(success = WiFi.setAutoConnect(true)))
continue;

//if (!(success = WiFi.begin(STASSID, STAPass)))
// continue;

Serial.print("\nSTA Connected to TP-LINK\n");

if (!(success = WiFi.setAutoReconnect(true)))
continue;

//struct softap_config config;
//wifi_softap_get_config(&config); // Get config first.
//config.max_connection = 8;
//wifi_softap_set_config(&config);

if (!(success = WiFi.softAP(APSSID, APPass, 11)))
continue;

struct softap_config config;
wifi_softap_get_config(&config); // Get config first.
config.max_connection = 8;
wifi_softap_set_config(&config);

Serial.printf("Waiting...\n");
delay(5000);

Serial.printf("\nmax_connections=%d num_connections=%d\n", config.max_connection, wifi_softap_get_station_num());

int num_connections = wifi_softap_get_station_num();

Serial.print("AP+STA Started\n");
}

for (int i=0; i<NSOCKETS; i++)
servers[i].begin();

pinMode(16, OUTPUT);

Serial.printf("\n\nServer Ready\n");
}


void ServerLoop()
{
static uint32_t last = 0;

if (millis() - statusTime > 5000)
{
Serial.printf("connections=%d ", wifi_softap_get_station_num());
for (int i = 0; i < NSOCKETS; i++)
Serial.printf("%c ", clients[i].connected() ? 'X' : '-');
Serial.print("\n");
statusTime = millis();
}

for (int i = 0; i < NSOCKETS; i++)
{
if (clients[i].connected())
{
digitalWrite(16, LOW);
if (clients[i].available())
Serial.printf("%d %6ld: ", i, millis() - last);
if (clients[i].available())
{
while (clients[i].available())
{
Serial.print((char)clients[i].read());
}
servers[i].begin();
last = millis();
}
}
if (!clients[i].connected())
{
digitalWrite(16, HIGH);
clients[i] = servers[i].available();
clients[i].setTimeout(10);
}
}
}

#else

void ClientSetup()
{
boolean success = false;

while (!success)
{
// Disconnect, if connected
WiFi.disconnect();

// Set Mode
if (!(success = WiFi.mode(WiFiMode_t::WIFI_STA)))
continue;

// Configure STA
if (!(success = WiFi.config(ClientIP, APIP, Netmask, APIP)))
continue;

WiFi.persistent(true);
if (!(success = WiFi.setAutoConnect(true)))
continue;

// Connect STA
if (!(success = WiFi.begin(APSSID, APPass)))
continue;

Serial.print("\nSTA Connected to AP\n");

if (!(success = WiFi.setAutoReconnect(true)))
continue;
}
for (int i=0; i<NSOCKETS; i++)
clients[i].setTimeout(10UL);

pinMode(16, OUTPUT);

Serial.printf("\n\nClient Ready\n");
}


void ClientLoop()
{
static int32_t last[NSOCKETS] = { 0, 0, 0, 0, 0, 0 };
static uint16_t cnt[NSOCKETS] = { 0, 0, 0, 0, 0, 0 };

for (int i = 0; i < NSOCKETS; i++)
{
if (!clients[i].connected())
{
digitalWrite(16, HIGH);
clients[i].connect(APIP, 8000);
}
if (clients[i].connected())
{
digitalWrite(16, LOW);
last[i] = millis();
clients[i].printf("Hello %u\n", (i * 100) + cnt[i]);
uint32_t delta = millis() - last[i];
Serial.printf("%d: Wrote %u %lu\n", i, (i * 100) + cnt[i]++, delta);
//delay(10);
clients[i].stop();
delay(1);
}
}
}
#endif


void setup()
{
Serial.begin(115200);
//Serial.setDebugOutput(true);
Serial.print("\n\n");

#if defined(SERVER)
ServerSetup();
#else
ClientSetup();
#endif
}



void loop()
{
#if defined(SERVER)
ServerLoop();
#else
ClientLoop();
#endif
}

Juraj

you still do not close the sockets on server side. they close themselves with a delay and the count of sockets is limited what I know.

I think opening more servers on one port is not a good idea. And restarting servers with begin makes it even more chaotic for TCP.

RayLivingston

Perhaps you can explain the correct logic?  Everything I've tried has problems.

Seems to me, the client initiates the communication, so it should end it, which is what I do, with the client.stop().  It's not clear to me exactly WHAT client.stop, and server.close actually do.  The documentation on this SUCKS.  If I eliminate the client.stop() on the client side, and instead do a server.close() on the server side, the behavior doesn't really change much - communication is still sporadic, and the server eventually just stops responding.

Regards,
Ray L.

Juraj

the client objects are same on both sides. they do not care if it is a server or client side. if one of them is closed, his counterpart doesn't know about it until a timeout (I saw 5 seconds in source code).

server listens on a dedicated socket (like 80 for web or 23 for telnet), but he only creates a new client as a counterpart for the remote client and then listens for the next calling remote client

wikipedia about sockets

RayLivingston

the client objects are same on both sides. they do not care if it is a server or client side. if one of them is closed, his counterpart doesn't know about it until a timeout (I saw 5 seconds in source code).
And that, I suspect, is part of the problem, I keep seeing - the server stops responding, because it's holding onto "dead" sockets.  There HAS to be a way to ensure BOTH ends close the socket, so the port is immediately freed.  But I have had zero luck finding a way to make that happen.  No matter what I try, eventually the whole thing just locks up for long periods, and it seems ONLY re-starting either the client or the server will get things going again.  I just tried running the WebSockets examples WebSocketServer, and WebSocketClient, both connecting through my TP-LINK router, and got EXACTLY the same behavior!  Is the 8266 just an unreliable POS??  I've wasted days of time on this, and I'm getting nowhere.  Using Ethernet, this is all pretty straight-forward, and the first time I tried, it worked on almost the first try.
Regards,
Ray L.

arduino_new

As far as I know there's no reliable way to check if a connection is alive. Instead you have to implement a check yourself (people call it the heart-beat check). So on server side, the server will send a heart-beat packet at random time (to reduce workload really) to a client socket, and within a defined time interval (usually 3 seconds) if server does not receive a respond to this heart-beat packet, the server will close this connection, free up resources and are ready to receive new client. On client side, you could do the same thing for the purpose of automatically reconnecting to server.

Btw, client.close() on both server and client sides is corresponding to client.disconnected(). In order for client.disconnected() to return TRUE, the other side must call .close(). If for some reasons the client resets the connection without calling .close(), the server will never know that client has been disconnected.

RayLivingston

There is no client.close(), only client.stop().  The server has both close() and stop(), which both do the same thing....

Among the most persistent problems I see is the connection is established, and even the very first message never gets through.

Regards,
Ray L.

RayLivingston

Well, this is interesting!  The root of all my problems appears to be the LCD display in the device I'm working on.  It has a 7"Nextion LCD display which, apparently, doubles as a WiFi jammer!  Unplug the power from the LCD, and the WiFi works perfectly.  Plug the LCD back in, andf the WiFi starts stuttering, and often just stops dead in its tracks.  No such problem with a 2.8" Nextion.  I fashioned a crude shield with some paper, tape, and aluminum foil, and I can now use the LCD and the WiFi together.

Never saw THAT one coming....


Regards,
Ray L.

RayLivingston

Now, on to the next headache:  How the he** do you get the NODEMCU to operate WITHOUT having a USB cable plugged into it?  Without the USB cable connected, it appears to be completely dead, even though it has good 5V power.

Regards,
Ray L.

Go Up