Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

websocket and client on same server - possible bug #50

Closed
denden4444 opened this issue Nov 1, 2019 · 13 comments
Closed

websocket and client on same server - possible bug #50

denden4444 opened this issue Nov 1, 2019 · 13 comments
Assignees
Labels
usage queshtion Queshtions about using the library, its interface and so on
Projects

Comments

@denden4444
Copy link

Hi Gil

Hope all's well with you.

As you may recall I have been testing your websockets on the ESP8266 and the tests have been good so far.
I'm hoping you could possibly identify/clarify some strange anomalies.
I am running both client and server on the same ESP8266.

Please refer to this image:
websockets client and server in one
A is a client (web browser) and needs to stay connected all the time until A decides it wants to disconnect
B is the ESP running both client and server.
When B receives a certain message , B fires up the websocket client portion and as w ebsocket client establishes a connection with C (C is running as a websockets server)
The above happen successfully (YAY ;-)) BUT
after B closes the connection (client disconnect) with C , the connection of A to B is lost. :-(
I have tried to set B not to close the connection to C ( no disconnect) but the same behavior occurs between A and B.
So I end up having to refresh the browser at A which re-establishes the connection from A to B.

Could you possibly shed some light as to how or where I could check and fix this ?

I'm not sure if this your software that may be causing the following :
Sometimes base on the problem in point 1. above , I am unable to re-establish a browser and/or websocket connection from A to B .
Its seems like B just stops servicing browser and/or websocket requests and sometimes a ping even though the serial console is still responding quite fine.
Any thoughts ?

Kind regards
Den

@gilmaimon
Copy link
Owner

Hi Den,

This sound interesting and as far as I know, could be either code issue or some library bug. Best thing to do is to share your code, it will allow me and anyone who wish to help recreate the problem and try and solve it. If you rather not share your code, try creating a smaller version of it such that it don't reveal anything you don't wish to share.

Best wishes,
Gil.

@gilmaimon gilmaimon added the possible-bug Something isn't working, and I think it is a bug label Nov 1, 2019
@gilmaimon gilmaimon added this to To do in Bugfixes via automation Nov 1, 2019
@gilmaimon gilmaimon self-assigned this Nov 1, 2019
@denden4444
Copy link
Author

denden4444 commented Nov 2, 2019

Hi Gil thanks for the reply ..
I just hope I''m loading the server portion up correctly and setting it to handle multiple clients.
I'll extract the necessary bits and post here as soon as I can.

Kind regards

Den

@denden4444
Copy link
Author

Hi Gil

Ok as a start let's go with the following :

Below is the basic websockets server (slightly modified , but should make no difference right ?)

Also included is a simple websocket client test html page (attached as TXT , just rename it to HTML ..it's a work in progress at the moment ..perhaps you like it ? Let me know :-)
If anyone would like to improve on it, I'd love a copy of the updated one.
websockettest05 - Copy.txt

Load up your websockets server onto and ESP8266 and then open the websockets test page in a browser from your client and test.
As a comparison use a websockets.org test too.
And you can also use a wss: connection.

I'm finding the websocket server with the example code on is crashing ( usually stops responding when connect and send is chosen) ..can you please confirm beahvior ?

The same code crashdumps the ESP8266 its on when I send it code from another ESP acting as a client. (Server labelled as B in diagram in previous message in this thread)
The stub of code I'm using to send is also below here : (Please note I have tried toggling the client.close() either side without much difference.
(This begs the question .. who should close the connection ... client or server or both ? I would like to control it from client side)

As an aside question is there any way of displaying which IP (and/or hostname) each client is coming in from ?

I will post server and client combined code in the next posting ( battling to keep eyes open now ;-0)

Kind regards
Den

CODE being used to send from B

//websockets client connect
void wsclient_connect(){
    // websocket client ...try to connect to Websockets server
  bool connected = client.connect(websockets_server_host, websockets_server_port, "/");
  if (connected) {
    Serial.println("Connececed!");
    client.send("#");
    //client.send("Hello Server");
  } else {
    Serial.println("Not Connected!");
  }

  // run callback when messages are received
  client.onMessage([&](WebsocketsMessage message) {
    Serial.print("Got Message: ");
    Serial.println(message.data());

    /*
             if (message.begin=="#"){
              Serial.print ("I got a hash #");
            }
    */

  }); //end of client websockets
   // close the connection
    client.close();
  //return;
}

SKETCH on C (acting as a websocket server)

/*
  Minimal Esp8266 Websockets Server

  This sketch:
        1. Connects to a WiFi network
        2. Starts a websocket server on port 81
        3. Waits for connections
        4. Once a client connects, it wait for a message from the client
        5. Sends an "echo" message to the client
        6. closes the connection and goes back to step 3

  Hardware:
        For this sketch you only need an ESP8266 board.

  Created 15/02/2019
  By Gil Maimon
  https://github.com/gilmaimon/ArduinoWebsockets
*/

#include <ArduinoWebsockets.h>
#include <ESP8266WiFi.h>

const char* ssid = "SSID"; //Enter SSID
const char* password = "PASS"; //Enter Password

using namespace websockets;

WebsocketsServer server;
void setup() {
  Serial.begin(115200);
  // Connect to wifi
  WiFi.begin(ssid, password);

  // Wait some time to connect to wifi
  for(int i = 0; i < 15 && WiFi.status() != WL_CONNECTED; i++) {
      Serial.print(".");
      delay(1000);
  }
  
  Serial.println("");
  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());   //You can get IP address assigned to ESP

  server.listen(81);
  Serial.print("Is server live? ");
  Serial.println(server.available());
}

void loop() {
  WebsocketsClient client = server.accept();
  if(client.available()) {
    WebsocketsMessage msg = client.readBlocking();

    // log
    Serial.print("Got Message: ");
    Serial.println(msg.data());

  if (msg.data()=="#"){
          Serial.print ("I got a hash #"); 
        }
//string C++ conversion to cstyle conversion
//const char *ptr1 = 0;
//ptr1= msg.data();
Serial.println("Char at index 0");
Serial.println (msg.data().charAt(0));
Serial.println("Char at index 1");
Serial.println (msg.data().charAt(1));
Serial.println("Char at index 2");
Serial.println (msg.data().charAt(2));
Serial.println("Char at index 3");
Serial.println (msg.data().charAt(3));


    // return echo
    client.send("Echo: " + msg.data());

    // close the connection
  //  client.close();
  }
  
  delay(100);
}

@gilmaimon
Copy link
Owner

Hi @denden4444

I will try to reproduce the bug this weekend. I think you should provide more code from sketch B. I see no client handling, which is the most important part.

When you say the code crashdumps the esp8266, what do you mean? What kind of crash is it (what is logged to serial)?

@denden4444
Copy link
Author

denden4444 commented Nov 5, 2019

Hi Gil
I have placed the code in a diagram .. hopefully it makes a little more sense
I have maintained the original elements A. B , C for continuous reference.
Here's the code at B:

//-------------------------Websockets ----------------------------------------

const char* websockets_server_host = "192.168.1.126"; //Enter server adress serverip_or_name
const uint16_t websockets_server_port = 81; // Enter server port
using namespace websockets;
WebsocketsServer wsserver;
WebsocketsClient client;

//i call the below function when this ESP must act as a client and connect to a remote server 
//websockets client connect
void wsclient_connect() {
  // websocket client ...try to connect to Websockets server
  bool connected = client.connect(websockets_server_host, websockets_server_port, "/");
  if (connected) {
    Serial.println("Connececed!");
    client.send("#");
    //client.send("Hello Server");
  } else {
    Serial.println("Not Connected!");
  }

  // run callback when messages are received
  client.onMessage([&](WebsocketsMessage message) {
    Serial.print("Got Message: ");
    Serial.println(message.data());
	/*
             if (message.begin=="#"){
              Serial.print ("I got a hash #");
            }
    */
}); //end of client websockets
  // close the connection
  client.close();
  //return;
}


//start 
 //start webSocket server and its event handler
  //initialize websockets server
  wsserver.listen(81);
  Serial.print("Is server live? ");
  Serial.println(wsserver.available());
  Serial.println("Server webSocket and event listener started .. ");
  
  
 //In main loop 
 //Gil websockets server 
  if (wsserver.poll()) {
    Serial.println("New Connection******************************");
    //client.close();
    client = wsserver.accept();
    client.onMessage([](WebsocketsClient & client, WebsocketsMessage msg) {

      Serial.printf("Message T%d B%d Pi%d Po%d C%d stream%d length: %u\n", msg.isText(), msg.isBinary(), msg.isPing(), msg.isPong(), msg.isClose(), msg.isPartial(), msg.data().length());

      // log
      Serial.print("Got Message: ");
      Serial.println(msg.data());
      client.send("Echo: " + msg.data()); //send the client what we got
      auto data = msg.data();

      if (data[0] == '#') {
        // Do something
        Serial.print ("if data[0] AUTO I got a hash #");
        addAR(msg.data().c_str());//add a new record
      }


    }); //endof client.onmessage function

  }//endof wsserver.poll

//also in main loop
//Gil websockets client
  if (client.available()) {
    client.poll();
	
  }//endof Gill websockets client
  

The code for C is in the above post (your example with a tiny change only for incoming message check.
websockets GIL issue code architecture 1

Let me know if you need anything else

@denden4444
Copy link
Author

denden4444 commented Nov 5, 2019

When you say the code crashdumps the esp8266, what do you mean? What kind of crash is it (what is logged to serial)?

The code on server C is the basic server example (see above)
I will run it again and send a paste of dump shortly

Kind regards

Den

********** PLEASE IGNORE THIS SPECIFIC REPLY .. MIRACULOUSLY C IS WORKING FINE NOW !!

Problem reported with B still exists -- closes client A connection after making a connection to C

@gilmaimon
Copy link
Owner

Hi @denden4444 ,

It seems like your B code tries to re-use the same WebsocketsClient instance twice. That won't work. Every time you call connect you should do it on a fresh, new, client. When you try to use the client you got from the server and connect with it to another server, the client won't work properly.

Also, notice that when you are doing client = //something you are loosing everything you had in client. If it was connected to something that connection will be lost.

Gil.

@denden4444
Copy link
Author

denden4444 commented Nov 6, 2019

Hi Gil
Thanksa million for the reply.
Was also thinking perhaps it's because of the shared namespace
What do you suggest ?
Would something like this work better ?

using namespace websockets;
WebsocketsServer wsserver;
WebsocketsClient client;
WebsocketsClient clientB;

I look forward to your reply.

Kind regards

Den

@denden4444
Copy link
Author

Hi Gil ..

Problem solved with the above ;-) , I therefore don't think there's any bug in the code .. perhaps you could confirm ?

I will try setup something simpler for you to test with and post here over the weekend.

So does this mean I could in fact run multiple instances of the websockets server on same chip as well ?
For example :

websocketServer wsserver0;
websocketServer wsserver1;

Kind regards

Den

@denden4444
Copy link
Author

denden4444 commented Nov 7, 2019

Hi Gil
Was taking an even closer look at my code :

Just need to clarify ...
Which of these two would be the correct usage :
1.

using namespace websockets;
WebsocketsServer wsserver;
WebsocketsClient client;
WebsocketsClient clientB;

2..

using namespace websockets;
WebsocketsServer server;
WebsocketsClient clientB;

Currently the code is working with 1. but I suspect 2 is most correct since your standalone server only uses this to start :

using namespace websockets;
WebsocketsServer server;

and later on in the main loop uses the following:

 WebsocketsClient client = server.accept();
  if(client.available()) {
    WebsocketsMessage msg = client.readBlocking();

I'd love to hear your thoughts and/or guidance.

Kind regards

Den

@gilmaimon
Copy link
Owner

Hi @denden4444,

First thing is you should understand what those lines do.. using namespace websockets just means the namespace websockets is imported into your code. Meaning from now on you don't need to write websockets::WebsocketsClient. you can just write WebsocketsClient.

Do you need 2 clients or one? Depending on what you are doing and how you write your code. If you can start and finish using the client from the server within one function, you don't need to declare it globally. In my server example, for example, I do something small with the client connection and then close it immediately. If you want to keep the connection alive, you will need a global variable to hold to client.

Gil.

@denden4444
Copy link
Author

denden4444 commented Nov 8, 2019

HI Gil

Thanks for the reply.

In terms of whats needed .. as the previous diagram shows.

At Server B
One webSockets Server ,
One webSockets Client .

Server C
One webSockets server

Could you kindly elaborate/expand on the below statement :

If you can start and finish using the client from the server within one function, you don't need to declare it globally.

The above can happen between B and C in the diagram.
B acts as a websockets client to C which acts as a websockets server

If you want to keep the connection alive, you will need a global variable to hold to client.

The above happens between A and B in the diagram:
Client browser A is a websockets client to websockets server B.

I hope that clears it up further.

Kind regards

Den

@gilmaimon gilmaimon added usage queshtion Queshtions about using the library, its interface and so on and removed possible-bug Something isn't working, and I think it is a bug labels Dec 11, 2019
@gilmaimon
Copy link
Owner

So this is a usage question rather than a bug. And the question seems to have more to do with general coding concepts than with the library itself, so I don't think it belongs here. Contact me privately.

Bugfixes automation moved this from To do to Done Dec 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
usage queshtion Queshtions about using the library, its interface and so on
Projects
Bugfixes
  
Done
Development

No branches or pull requests

2 participants