LWIP- mulitple client example
LWIP- mulitple client example
Hi All,
Does anyone have an example of multiple clients connected to one server through one Port ?
What is the best practice to do this?
Thanks
Imtiaz
Does anyone have an example of multiple clients connected to one server through one Port ?
What is the best practice to do this?
Thanks
Imtiaz
Re: LWIP- mulitple client example
Howdy imtiaz,
This is a common story for TCP/IP sockets programming. I think if you were to study the TCP/IP sockets API in general, the answer you would find will work perfectly in an ESP32 environment and you will be pleased with the results. TCP/IP sockets is a rich and powerful API that appears to be fully implemented in the ESP32. If you get a book on TCP/IP sockets and study that, you will be well rewarded. I'm sure you can also bring together your study from web based articles.
At a high level, you would create a C application that executes:
The above is pseudo code ... but you would create a socket that will be used to represent the endpoint on the ESP32 to which clients will connect. You will then bind it to the port number on the ESP32 that you want to listen upon. You will then instruct the ESP32 to listen on that socket with a maximum number of un-accepted clients being supported.
Now you will enter a loop where you will call "accept()". This is the core function. When called, it blocks waiting for an incoming client connection request. In the ESP32, it will block the current task but will allow parallel tasks to continue. When we wake up, it is because we have received a new client request. Now we have design choices ... we make process the client request immediately and then close it down ... which we can do if the client processing is short ... OR ... we can spawn a new FreeRTOS task and pass it the newly received socket representing the client request and have THAT task handle it in parallel. We then go back round the loop and wait for the next incoming client.
All of this is business as usual in TCP/IP sockets programming.
This is a common story for TCP/IP sockets programming. I think if you were to study the TCP/IP sockets API in general, the answer you would find will work perfectly in an ESP32 environment and you will be pleased with the results. TCP/IP sockets is a rich and powerful API that appears to be fully implemented in the ESP32. If you get a book on TCP/IP sockets and study that, you will be well rewarded. I'm sure you can also bring together your study from web based articles.
At a high level, you would create a C application that executes:
Code: Select all
int s = socket();
bind(s, port);
listen(backlog);
while(true) {
int newClient = accept(s);
createTaskToHandleClient(newClient);
}
Now you will enter a loop where you will call "accept()". This is the core function. When called, it blocks waiting for an incoming client connection request. In the ESP32, it will block the current task but will allow parallel tasks to continue. When we wake up, it is because we have received a new client request. Now we have design choices ... we make process the client request immediately and then close it down ... which we can do if the client processing is short ... OR ... we can spawn a new FreeRTOS task and pass it the newly received socket representing the client request and have THAT task handle it in parallel. We then go back round the loop and wait for the next incoming client.
All of this is business as usual in TCP/IP sockets programming.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: LWIP- mulitple client example
Hi Kolban,
Many thanks for your excellent reply - . I have a couple of questions:
If we do as you suggested "OR ... we can spawn a new FreeRTOS task and pass it the newly received socket representing the client request and have THAT task handle it in parallel"
1 ) Is that PORT still blocked to other clients while we are processing the client request ?
2) If Yes above - How does the client handle a connection decline from the server?
Our messages on that PORT would be small - 500 byte Max - in that case would it be sufficient to have it process blocking and the client can retry ?
Imtiaz
Many thanks for your excellent reply - . I have a couple of questions:
If we do as you suggested "OR ... we can spawn a new FreeRTOS task and pass it the newly received socket representing the client request and have THAT task handle it in parallel"
1 ) Is that PORT still blocked to other clients while we are processing the client request ?
2) If Yes above - How does the client handle a connection decline from the server?
Our messages on that PORT would be small - 500 byte Max - in that case would it be sufficient to have it process blocking and the client can retry ?
Imtiaz
Re: LWIP- mulitple client example
When you write a socket based application, the parameter supplied to the "listen()" API defines how many client connects can be allowed to connect BETWEEN calls to accept(). The way to think of it is as a backlog of queued connections waiting to be processed. Everytime you call accept() you are either blocking waiting for a connection to arrive or else you return immediately with the first client that arrived that has not yet been accepted.
The data size is not the primary issue in your design, but rather how long it takes to process a request before being ready to process the next one and combine that with the arrival rate of requests.
For example ... if one request arrives per second and it takes 1/2 a second to process a request ... then you are safe to process the request in the accept() loop as you won't be late for the next client connecting. However, the problems come in when we have "bursty" traffic ... how then should we handle? The more common case in sockets is where we have only a few client connections (eg. telnet clients) but they are maintained for hours at a time. If we process a client connection in the accept loop, we are tacitly saying that we will ONLY be processing one client at a time. If we want to allow multiple clients to be processed concurrently, then you would accept() a client connection and then spawn a task to handle it and since the task is now running in parallel, we can go and block accepting() the next client. Please realize that an ESP32 is not a PC. PC's can handle hundreds (and servers thousands) of concurrent connections. Our little ESP32 will start to fall over if it tries to maintain too many concurrent sockets connections. I believe there is a configurable limit that won't be more than 16 ... but it is unlikely we would have the RAM for 16 concurrent sockets at the best of times.
The data size is not the primary issue in your design, but rather how long it takes to process a request before being ready to process the next one and combine that with the arrival rate of requests.
For example ... if one request arrives per second and it takes 1/2 a second to process a request ... then you are safe to process the request in the accept() loop as you won't be late for the next client connecting. However, the problems come in when we have "bursty" traffic ... how then should we handle? The more common case in sockets is where we have only a few client connections (eg. telnet clients) but they are maintained for hours at a time. If we process a client connection in the accept loop, we are tacitly saying that we will ONLY be processing one client at a time. If we want to allow multiple clients to be processed concurrently, then you would accept() a client connection and then spawn a task to handle it and since the task is now running in parallel, we can go and block accepting() the next client. Please realize that an ESP32 is not a PC. PC's can handle hundreds (and servers thousands) of concurrent connections. Our little ESP32 will start to fall over if it tries to maintain too many concurrent sockets connections. I believe there is a configurable limit that won't be more than 16 ... but it is unlikely we would have the RAM for 16 concurrent sockets at the best of times.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: LWIP- mulitple client example
Hi Kolban,
Got it , thanks - that clears up a lot for me and yep I'm well aware of the limitations being an embedded guy.
Many thanks for your time .
Regards
Imtiaz
Got it , thanks - that clears up a lot for me and yep I'm well aware of the limitations being an embedded guy.
Many thanks for your time .
Regards
Imtiaz
Re: LWIP- mulitple client example
Hi Neil,
I am using your multiple socket connection sample to learn/test socket connections and it works well.
I want to send some data when client connects and if client disconnects, I need to switch off peripheral and also do some clean up.
So question is, how to detect if a client has disconnected in the loop where data is being continuously sent.
In your sample code the task completes after some printing messages...
Thanks in advance.
I am using your multiple socket connection sample to learn/test socket connections and it works well.
I want to send some data when client connects and if client disconnects, I need to switch off peripheral and also do some clean up.
So question is, how to detect if a client has disconnected in the loop where data is being continuously sent.
In your sample code the task completes after some printing messages...
Thanks in advance.
Re: LWIP- mulitple client example
The good news about the ESP-IDF sockets implementation is that is appears pretty faithful to "normal" sockets so any/all recipes that you find on the Internet relating to sockets should work just fine in the ESP-IDF environment.
If a peer to the ESP32 disconnects/closes its connection, then the next read on ESP32 will return an error or the next write on the ESP32 will return an error ... or you can "ask" the socket about its state (if you are doing neither a read nor a write) using the "select()" system call.
If a peer to the ESP32 disconnects/closes its connection, then the next read on ESP32 will return an error or the next write on the ESP32 will return an error ... or you can "ask" the socket about its state (if you are doing neither a read nor a write) using the "select()" system call.
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Re: LWIP- mulitple client example
Thank you for the response.
My sendData function is like this. What do you suggest to check the socket disconnect?
My sendData function is like this. What do you suggest to check the socket disconnect?
Code: Select all
static void sendData(int sock)
{
while(1)
{
if (sock < 0) // how to check disconnect???
{
// client disconnected???
ESP_LOGI(TAG, "[%d]",(int)sock);
break;
}
char *line = readLine(MY_UART);
ESP_LOGI(TAG, "[%d]: %s",(int)sock, line);
send(sock,line,strlen(line),0);
}
ESP_LOGI(TAG, "Socket #:%d",(int)sock);
close(sock);
}
Re: LWIP- mulitple client example
I just changed it to this using bytesSent and seems to be working... does it look right?
I am new to socket programming
I am new to socket programming
Code: Select all
static void sendData(int sock)
{
int bytesSent=0;
while(1)
{
if (bytesSent < 0) // check disconnect
{
// client disconnected???
ESP_LOGI(TAG, "[%d]",(int)sock);
break;
}
char *line = readLine(MY_UART);
ESP_LOGI(TAG, "[%d]: %s",(int)sock, line);
bytesSent = send(sock,line,strlen(line),0);
}
ESP_LOGI(TAG, "Socket #:%d",(int)sock);
close(sock);
}
Re: LWIP- mulitple client example
That looks great to me. The key thing is to study the sockets API ... and there are Unix man pages on these ... for example:
https://linux.die.net/man/2/send
Get familiar with reading these pages. See for example the "Return Value" section. See that you get -1 on error and then the global errno is then set.
There are some good on-line courses on sockets programming and some great books on the subject. Other than that, no better advice than just keep plugging away. An alternate loop style (and this is just taste) might have been:
https://linux.die.net/man/2/send
Get familiar with reading these pages. See for example the "Return Value" section. See that you get -1 on error and then the global errno is then set.
There are some good on-line courses on sockets programming and some great books on the subject. Other than that, no better advice than just keep plugging away. An alternate loop style (and this is just taste) might have been:
Code: Select all
int bytesSent;
do {
...
bytesSent = send(...);
} while(bytesSent > 0);
Free book on ESP32 available here: https://leanpub.com/kolban-ESP32
Who is online
Users browsing this forum: No registered users and 148 guests