Ethernet // EthernetServer , always take at least 2 sockets ?

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

Do you mean the client web browser makes 2 requests?

If so, that is because most browsers make the page request, then requests the favicon.

no i mean if i pull socket status when a SINGLE CLIENT is connected

(with putty or simple telnet client , not a browser)

for (int i = 0; i < MAX_SOCK_NUM; i++) {
  byte SockStat = W5100.readSnSR(i);             // Socket Status
  unsigned int SrcPort = W5100.readSnPORT(i);    // Source Port
  unsigned int DestPort = W5100.readSnDPORT(i);  // Destination Port
  byte DestIp[4];
  W5100.readSnDIPR(i, DestIp);  // Destination IP Address
  byte DestMac[6];
  W5100.readSnDHAR(i, DestMac);  // Destination MAC Address

  Serial.print(F("Socket# "));
  Serial.print(i);
  Serial.print(F(" : 0x"));
  Serial.print(SockStat, HEX);
  Serial.print(F("  SrcPort : "));
  Serial.print(SrcPort);
  Serial.print(F("  "));
  for (int j = 0; j < 4; j++) {
    Serial.print(DestIp[j], DEC);
    if (j < 3) Serial.print(".");
  }
  Serial.print(F("  DestPort : "));
  Serial.print(DestPort);
  Serial.println(F(""));
}

i have 2 socket used when client connected , i would like to have only one if possible at all

.

one socket that is still listening on port 1234

and another socket that is an active opened connection on port 1234

Socket# 3 : 0x17  SrcPort : 1234  192.168.x.x  DestPort : 65324
Socket# 6 : 0x14  SrcPort : 1234   0.0.0.0  DestPort : 0

since a would want a single client server , i was hopping it could stop listening while client is connected

because with 2 or 3 server it become a problem and i run out of socket (Mega with w5500)

(remote OTA update , remote debug , NTP , MQTT)

Are you checking the socket status?

If no client connected, there should be one socket LISTENING for a new connection.

If a client is connected, that uses one socket CONNECTED.

That’s 2.

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();
  }

}

W5100.writeSnSR(s,0)

if i use THIS on the listening socket , it get released , but recreated immediately by Server.available(); in loop

Tried to look at ethernet.h ethernet.cpp ethernetserver.cpp to add server.stop()

but this is beyond what my amateur level arduino enthusiat can do

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();
  }

For more information see the Server class reference, I hope it somehow helps you.

How does the server code know it’s you connecting?

If another device connects first, it will block you.

What is your goal?

simple and must be doable , thanks

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 :wink:

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.