use static list of client connections in socket server
This commit is contained in:
parent
c893025cd3
commit
8c02b21277
|
@ -51,15 +51,36 @@ class GwClient{
|
||||||
GwBuffer *buffer;
|
GwBuffer *buffer;
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
int overflows;
|
int overflows;
|
||||||
|
String remoteIp;
|
||||||
private:
|
private:
|
||||||
Writer *writer;
|
Writer *writer=NULL;
|
||||||
public:
|
public:
|
||||||
GwClient(wiFiClientPtr client,GwLog *logger){
|
GwClient(wiFiClientPtr client,GwLog *logger){
|
||||||
this->client=client;
|
this->client=client;
|
||||||
this->logger=logger;
|
this->logger=logger;
|
||||||
buffer=new GwBuffer(logger);
|
buffer=new GwBuffer(logger);
|
||||||
overflows=0;
|
overflows=0;
|
||||||
|
if (client != NULL){
|
||||||
writer=new Writer(client);
|
writer=new Writer(client);
|
||||||
|
remoteIp=client->remoteIP().toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void setClient(wiFiClientPtr client){
|
||||||
|
this->client=client;
|
||||||
|
buffer->reset();
|
||||||
|
overflows=0;
|
||||||
|
if (writer) delete writer;
|
||||||
|
writer=NULL;
|
||||||
|
if (client){
|
||||||
|
writer=new Writer(client);
|
||||||
|
remoteIp=client->remoteIP().toString();
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
remoteIp=String("---");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
bool hasClient(){
|
||||||
|
return client != NULL;
|
||||||
}
|
}
|
||||||
~GwClient(){
|
~GwClient(){
|
||||||
delete writer;
|
delete writer;
|
||||||
|
@ -68,7 +89,7 @@ class GwClient{
|
||||||
if (len == 0) return true;
|
if (len == 0) return true;
|
||||||
size_t rt=buffer->addData(data,len);
|
size_t rt=buffer->addData(data,len);
|
||||||
if (rt < len){
|
if (rt < len){
|
||||||
LOG_DEBUG(GwLog::LOG,"overflow on %s",client->remoteIP().toString().c_str());
|
LOG_DEBUG(GwLog::LOG,"overflow on %s",remoteIp.c_str());
|
||||||
overflows++;
|
overflows++;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -78,12 +99,16 @@ class GwClient{
|
||||||
return buffer->usedSpace() > 0;
|
return buffer->usedSpace() > 0;
|
||||||
}
|
}
|
||||||
GwBuffer::WriteStatus write(){
|
GwBuffer::WriteStatus write(){
|
||||||
|
if (! writer) {
|
||||||
|
LOG_DEBUG(GwLog::LOG,"write called on empty client");
|
||||||
|
return GwBuffer::ERROR;
|
||||||
|
}
|
||||||
GwBuffer::WriteStatus rt=buffer->fetchData(writer,false);
|
GwBuffer::WriteStatus rt=buffer->fetchData(writer,false);
|
||||||
if (rt != GwBuffer::OK){
|
if (rt != GwBuffer::OK){
|
||||||
LOG_DEBUG(GwLog::DEBUG+1,"write returns %d on %s",rt,client->remoteIP().toString().c_str());
|
LOG_DEBUG(GwLog::DEBUG+1,"write returns %d on %s",rt,remoteIp.c_str());
|
||||||
}
|
}
|
||||||
if (writer->timeOut ){
|
if (writer->timeOut ){
|
||||||
LOG_DEBUG(GwLog::LOG,"timeout on %s",client->remoteIP().toString().c_str());
|
LOG_DEBUG(GwLog::LOG,"timeout on %s",remoteIp.c_str());
|
||||||
return GwBuffer::ERROR;
|
return GwBuffer::ERROR;
|
||||||
}
|
}
|
||||||
return rt;
|
return rt;
|
||||||
|
@ -94,9 +119,14 @@ class GwClient{
|
||||||
GwSocketServer::GwSocketServer(const GwConfigHandler *config,GwLog *logger){
|
GwSocketServer::GwSocketServer(const GwConfigHandler *config,GwLog *logger){
|
||||||
this->config=config;
|
this->config=config;
|
||||||
this->logger=logger;
|
this->logger=logger;
|
||||||
|
maxClients=config->getInt(config->maxClients);
|
||||||
|
clients=new gwClientPtr[maxClients];
|
||||||
|
for (int i=0;i<maxClients;i++){
|
||||||
|
clients[i]=gwClientPtr(new GwClient(wiFiClientPtr(NULL),logger));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
void GwSocketServer::begin(){
|
void GwSocketServer::begin(){
|
||||||
server=new WiFiServer(config->getInt(config->serverPort),config->getInt(config->maxClients));
|
server=new WiFiServer(config->getInt(config->serverPort),maxClients);
|
||||||
server->begin();
|
server->begin();
|
||||||
logger->logString("Socket server created, port=%d",
|
logger->logString("Socket server created, port=%d",
|
||||||
config->getInt(config->serverPort));
|
config->getInt(config->serverPort));
|
||||||
|
@ -107,45 +137,62 @@ void GwSocketServer::loop()
|
||||||
{
|
{
|
||||||
WiFiClient client = server->available(); // listen for incoming clients
|
WiFiClient client = server->available(); // listen for incoming clients
|
||||||
|
|
||||||
if (client){
|
if (client)
|
||||||
|
{
|
||||||
logger->logString("new client connected from %s",
|
logger->logString("new client connected from %s",
|
||||||
client.remoteIP().toString().c_str());
|
client.remoteIP().toString().c_str());
|
||||||
fcntl(client.fd(), F_SETFL, O_NONBLOCK);
|
fcntl(client.fd(), F_SETFL, O_NONBLOCK);
|
||||||
gwClientPtr newClient(new GwClient(wiFiClientPtr(new WiFiClient(client)),logger));
|
bool canHandle = false;
|
||||||
clients.push_back(newClient);
|
for (int i = 0; i < maxClients; i++)
|
||||||
|
{
|
||||||
|
if (!clients[i]->hasClient())
|
||||||
|
{
|
||||||
|
clients[i]->setClient(wiFiClientPtr(new WiFiClient(client)));
|
||||||
|
logger->logString("set client as number %d", i);
|
||||||
|
canHandle = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!canHandle)
|
||||||
|
{
|
||||||
|
logger->logDebug(GwLog::ERROR, "no space to store client, disconnect");
|
||||||
|
client.stop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
//sending
|
//sending
|
||||||
for (auto it = clients.begin(); it != clients.end();it++){
|
for (int i = 0; i < maxClients; i++)
|
||||||
GwBuffer::WriteStatus rt=(*it)->write();
|
{
|
||||||
if (rt == GwBuffer::ERROR){
|
gwClientPtr client = clients[i];
|
||||||
LOG_DEBUG(GwLog::ERROR,"write error on %s, closing",(*it)->client->remoteIP().toString().c_str());
|
if (!client->hasClient())
|
||||||
(*it)->client->stop();
|
continue;
|
||||||
|
GwBuffer::WriteStatus rt = client->write();
|
||||||
|
if (rt == GwBuffer::ERROR)
|
||||||
|
{
|
||||||
|
LOG_DEBUG(GwLog::ERROR, "write error on %s, closing", client->remoteIp.c_str());
|
||||||
|
client->client->stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (auto it = clients.begin(); it != clients.end();it++)
|
for (int i = 0; i < maxClients; i++)
|
||||||
{
|
{
|
||||||
if ((*it) != NULL)
|
gwClientPtr client = clients[i];
|
||||||
|
if (!client->hasClient())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!client->client->connected())
|
||||||
{
|
{
|
||||||
if (!(*it)->client->connected())
|
logger->logString("client %d disconnect %s", i, client->remoteIp.c_str());
|
||||||
{
|
client->client->stop();
|
||||||
logger->logString("client disconnect");
|
client->setClient(NULL);
|
||||||
(*it)->client->stop();
|
|
||||||
clients.erase(it);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
while ((*it)->client->available())
|
while (client->client->available())
|
||||||
{
|
{
|
||||||
char c = (*it)->client->read();
|
char c = client->client->read();
|
||||||
//TODO: read data
|
//TODO: read data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
it = clients.erase(it); // Should have been erased by StopClient
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
void GwSocketServer::sendToClients(const char *buf){
|
void GwSocketServer::sendToClients(const char *buf){
|
||||||
int len=strlen(buf);
|
int len=strlen(buf);
|
||||||
|
@ -155,11 +202,14 @@ void GwSocketServer::sendToClients(const char *buf){
|
||||||
len++;
|
len++;
|
||||||
buffer[len]=0x0a;
|
buffer[len]=0x0a;
|
||||||
len++;
|
len++;
|
||||||
for (auto it = clients.begin() ; it != clients.end(); it++) {
|
for (int i = 0; i < maxClients; i++)
|
||||||
if ( (*it) != NULL && (*it)->client->connected() ) {
|
{
|
||||||
bool rt=(*it)->enqueue((uint8_t*)buffer,len);
|
gwClientPtr client = clients[i];
|
||||||
|
if (! client->hasClient()) continue;
|
||||||
|
if ( client->client->connected() ) {
|
||||||
|
bool rt=client->enqueue((uint8_t*)buffer,len);
|
||||||
if (!rt){
|
if (!rt){
|
||||||
LOG_DEBUG(GwLog::DEBUG,"overflow in send to %s",(*it)->client->remoteIP().toString().c_str());
|
LOG_DEBUG(GwLog::DEBUG,"overflow in send to %s",client->remoteIp.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -167,5 +217,12 @@ void GwSocketServer::sendToClients(const char *buf){
|
||||||
}
|
}
|
||||||
|
|
||||||
int GwSocketServer::numClients(){
|
int GwSocketServer::numClients(){
|
||||||
return clients.size();
|
int num=0;
|
||||||
|
for (int i = 0; i < maxClients; i++){
|
||||||
|
if (clients[i]->hasClient()) num++;
|
||||||
|
}
|
||||||
|
return num;
|
||||||
|
}
|
||||||
|
GwSocketServer::~GwSocketServer(){
|
||||||
|
|
||||||
}
|
}
|
|
@ -2,7 +2,6 @@
|
||||||
#define _GWSOCKETSERVER_H
|
#define _GWSOCKETSERVER_H
|
||||||
#include "GWConfig.h"
|
#include "GWConfig.h"
|
||||||
#include "GwLog.h"
|
#include "GwLog.h"
|
||||||
#include <list>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
#include <WiFi.h>
|
#include <WiFi.h>
|
||||||
|
|
||||||
|
@ -13,10 +12,12 @@ class GwSocketServer{
|
||||||
private:
|
private:
|
||||||
const GwConfigHandler *config;
|
const GwConfigHandler *config;
|
||||||
GwLog *logger;
|
GwLog *logger;
|
||||||
std::list<gwClientPtr> clients;
|
gwClientPtr *clients;
|
||||||
WiFiServer *server=NULL;
|
WiFiServer *server=NULL;
|
||||||
|
int maxClients;
|
||||||
public:
|
public:
|
||||||
GwSocketServer(const GwConfigHandler *config,GwLog *logger);
|
GwSocketServer(const GwConfigHandler *config,GwLog *logger);
|
||||||
|
~GwSocketServer();
|
||||||
void begin();
|
void begin();
|
||||||
void loop();
|
void loop();
|
||||||
void sendToClients(const char *buf);
|
void sendToClients(const char *buf);
|
||||||
|
|
Loading…
Reference in New Issue