i am playing with Ethernet to analyse how it work (using ethernet with a lot of sketch for years but trying to do more now)
and i just discover (maybe i am wrong) , that it take 2 socket to handle a server !
EthernetServer TestServer(1234);
void setup() {
Serial.begin(9600);
TestServer.begin(); // open/use a socket with status 0x14 = waiting for a connection , and always stay there listening
}
void loop() {
EthernetClient TestClient = TestServer.available();
// use a NEW socket with status 0x17 = connected
// when client drop connection , socket status become 0x1C or 0x00
if (TestClient ) {
if (TestClient.available()) {
Serial.print("data : ");
Serial.println(TestClient.read());
}
}
}
can i release the waiting socket when a client connect , and open it again when the client close ? so far no sucess
there is no server.close() server.stop() server.end() to handle this pseudo manually
yep exactly my problem , if a client connect , i would like that it take the place of the listening socket(or release the listening socket) and stop any new client from connecting on the same port , using only one socket in the end , until client disconnect and socket go to listening again.
maybe this can’t be done on arduino with default ethernet library or maybe i am all wrong about socket and ethernet in general
I used this code in the past to close clients.
void closeServer()
{
for (int i = 0; i < MAX_SOCK_NUM; i++) {
uint8_t s = W5100.readSnSR(i);
if((s == 0x14) || (s == 0x17) || (s == 0x1C)) {
unlisten(i);
}
socketStat[i] = W5100.readSnSR(i);
}
}
byte unlisten(SOCKET s)
{
// W5100.writeMR(0xFF);
W5100.writeSnSR(s,0);
return 1;
}
idealy i would want something like this to stop the listening socket/server while a client is connected.
EthernetServer TestServer(1234);
byte ServerStatus = 1;
void setup() {
Serial.begin(9600);
TestServer.begin(); // open/use a socket with status 0x14 = waiting for a connection , and always stay there listening
}
void loop() {
EthernetClient TestClient = TestServer.available();
// use a NEW socket with status 0x17 when a client connect
// when client drop connection , socket status become 0x1C or 0x00
if (TestClient) {
if (ServerStatus == 1) {
ServerStatus = 0;
TestServer.stop(); // STOP or END , DOES NOT EXIST IN ETHERNETSERVER
}
if (TestClient.available()) {
Serial.print("data : ");
Serial.println(TestClient.read());
}
}
else if (!TestClient.connected() && ServerStatus == 0) {
ServerStatus = 1;
TestServer.begin();
}
}
First I must tell you that I've never used EthernetServer myself but I'm familiar with programming the sockets. Normally the server opens a listening socket that accepts new connection and then opens a connection socket and starts a new task to handle the connection while the server task continues listening.
Your program on the other hand uses only one task so all you have to do is not calling TestServer.available() as long as TestClient is doing its job to get the behaviour you desire.
Normal behaviour. Since your server is bound to all local address (the "0.0.0.0" means that, and it's the EthernetServer class) when a client connects a socket is allocated to that specific address (the "192.168.x.x", the EthernetClient class) to handle that specific client-server communication over that specific subnet.
I've never had to worry about this, but I try my little tip (try it, I can't guarantee it will work). First of all bind the server to the specific and fixed Arduino server IP address and not to 0.0.0.0.
Then if you need to accept only one client at the time and refuse others, I think you could first use accept() function instead of available(). It returns an EthernetClient object if a client is connected so a flag could be raised to signal the client presence, then while the client is still connected refuse any other connections by immediately calling otherClient.stop() after "server.accept()". When the first (and only) client disconnects clear the flag.
something like this (note: untested!):
...
EthernetClient currentClient;
EthernetClient newClient;
bool isClientConnected = false;
...
newClient = server.accept();
if (newClient) {
if (!isClientConnected) {
currentClient = newClient;
isClientConnected = true;
...
// At the end of operations or client disconnected
// (not necessarily here, depends on how the connection is handled)
isClientConnected = false;
currentClient = null; // I don't know if it's needed...
...
} else {
// Refuse any other client
newClient.stop();
}
i have , remoteOTA server , telnet remote debug server , ntp , mqtt , and with them using 2 socket when something is connected i get in situation where i hit 8 socket used.
everything is on local network , and i won’t have more than one client per server at any given time. so closing the listening port while a client is connected won’t be an issue
.
will try to write code and report back with what i got in a moment
I would try to find out why the server ends up with 8 sockets connected.
The code I posted was to prevent the situation you have now, except mine was on the internet, subject to port scanners. If a telnet client connects and doesn’t send anything, one socket gone. Do it again 2 sockets gone. Do it again…
My code would keep track of how long a device was connected without sending anything. Don’t send anything for a minute, and the code boots that device.
i end up with many socket “by design” , because i have many different use for a single W5500
maybe too much
.
i managed to get it to do what i want but had to modify server.accept() function in Ethernet library.
impossible to avoid server.accept() or server.availble() to call server.begin() , because it call server.begin() at the end of both server.accept() or server.availble()
even if i stop call to server.accept() or server.availble() when a client connect , it still call begin() at least once when i handle my first client.
regarding this , i have only ONE port from the internet that is opened on this board , and my remote client is another arduino that talk with “language” of my own , when a client connect if it doesnt send the right data it get rejected immediately with no response.
Then my client send special ping data every 30s to tell if still connected, if no ping it mean connection drop , then socket released to accept new client try.