Linux: Fix Ethernet client and server (#836)
- Fix documentation. - Add function close() to client class. - Function connected() now return true if the connection is in stablished state or there is still unread data. - Update hasClient() to check if any client has disconnected. - Fix _accept() to better handle the case of maximum clients reached. - Fix peek() to return the next byte of the read queue. - Simplifies write() of the server class. - Implements flush(). - Updates read() to non-blocking type, the same way as in Arduino.
This commit is contained in:
committed by
Henrik Ekblad
parent
95f719b604
commit
a4c7b249c1
@@ -19,6 +19,7 @@
|
||||
* Based on Arduino ethernet library, Copyright (c) 2010 Arduino LLC. All right reserved.
|
||||
*/
|
||||
|
||||
#include "EthernetServer.h"
|
||||
#include <cstdio>
|
||||
#include <sys/socket.h>
|
||||
#include <cstring>
|
||||
@@ -30,7 +31,6 @@
|
||||
#include <fcntl.h>
|
||||
#include "log.h"
|
||||
#include "EthernetClient.h"
|
||||
#include "EthernetServer.h"
|
||||
|
||||
EthernetServer::EthernetServer(uint16_t port, uint16_t max_clients) : port(port),
|
||||
max_clients(max_clients), sockfd(-1)
|
||||
@@ -108,6 +108,24 @@ void EthernetServer::begin(IPAddress address)
|
||||
|
||||
bool EthernetServer::hasClient()
|
||||
{
|
||||
// Check if any client has disconnected
|
||||
for (size_t i = 0; i < clients.size(); ++i) {
|
||||
EthernetClient client(clients[i]);
|
||||
if (!client.connected()) {
|
||||
// Checks if this disconnected client is also on the new clients list
|
||||
for (std::list<int>::iterator it = new_clients.begin(); it != new_clients.end(); ++it) {
|
||||
if (*it == clients[i]) {
|
||||
new_clients.erase(it);
|
||||
break;
|
||||
}
|
||||
}
|
||||
client.stop();
|
||||
clients[i] = clients.back();
|
||||
clients.pop_back();
|
||||
logDebug("Ethernet client disconnected.\n");
|
||||
}
|
||||
}
|
||||
|
||||
_accept();
|
||||
|
||||
return !new_clients.empty();
|
||||
@@ -136,14 +154,9 @@ size_t EthernetServer::write(const uint8_t *buffer, size_t size)
|
||||
|
||||
while (i < clients.size()) {
|
||||
EthernetClient client(clients[i]);
|
||||
if (client.connected()) {
|
||||
if (client.status() == ETHERNETCLIENT_W5100_ESTABLISHED) {
|
||||
n += client.write(buffer, size);
|
||||
i++;
|
||||
} else if (!client.available()) {
|
||||
client.stop();
|
||||
clients[i] = clients.back();
|
||||
clients.pop_back();
|
||||
logDebug("Client disconnected.\n");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,36 +183,6 @@ void EthernetServer::_accept()
|
||||
struct sockaddr_storage client_addr;
|
||||
char ipstr[INET_ADDRSTRLEN];
|
||||
|
||||
if (new_clients.size() + clients.size() == max_clients) {
|
||||
// no free slots, search for a dead client
|
||||
bool no_free_slots = true;
|
||||
for (size_t i = 0; i < clients.size();) {
|
||||
EthernetClient client(clients[i]);
|
||||
if (client.connected() || client.available()) {
|
||||
i++;
|
||||
} else {
|
||||
clients[i] = clients.back();
|
||||
clients.pop_back();
|
||||
no_free_slots = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (no_free_slots) {
|
||||
for (std::list<int>::iterator it = new_clients.begin(); it != new_clients.end(); ++it) {
|
||||
EthernetClient client(*it);
|
||||
if (!client.connected() && !client.available()) {
|
||||
new_clients.erase(it);
|
||||
no_free_slots = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (no_free_slots) {
|
||||
logDebug("Max number of ethernet clients reached.\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
sin_size = sizeof client_addr;
|
||||
new_fd = accept(sockfd, (struct sockaddr *)&client_addr, &sin_size);
|
||||
if (new_fd == -1) {
|
||||
@@ -209,6 +192,13 @@ void EthernetServer::_accept()
|
||||
return;
|
||||
}
|
||||
|
||||
if (clients.size() == max_clients) {
|
||||
// no free slots, search for a dead client
|
||||
close(new_fd);
|
||||
logDebug("Max number of ethernet clients reached.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
new_clients.push_back(new_fd);
|
||||
clients.push_back(new_fd);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user