EthernetServer.cpp multiple connections issue - Not iterating thru active socket

Hello,

Can any help explain what is going on with these two ethernetclient.cpp functions? I am having an issue with multiple client connections. I think part of the problem is with available function. I don't think it is iterating thru all of the active incoming socket connections, of which there can be 4 with the w5100 ethernetshield.

Thanks,

-ren

void EthernetServer::accept()
{
int listening = 0;

for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);

if (EthernetClass::_server_port[sock] == _port) {
if (client.status() == SnSR::LISTEN) {
listening = 1;
}
else if (client.status() == SnSR::CLOSE_WAIT && !client.available()) {
client.stop();
}
}
}

if (!listening) {
begin();
}
}

EthernetClient EthernetServer::available()
{
accept();

for (int sock = 0; sock < MAX_SOCK_NUM; sock++) {
EthernetClient client(sock);
if (EthernetClass::_server_port[sock] == _port &&
(client.status() == SnSR::ESTABLISHED ||
client.status() == SnSR::CLOSE_WAIT)) {
if (client.available()) {
// XXX: don't always pick the lowest numbered socket.
return client;
}
}
}

return EthernetClient(MAX_SOCK_NUM);
}

How are you determining it is not responding to the connection requests?

There are 4 sockets, but the ethernet web server library code will service only one socket (connection) at a time. All other connections must wait their turn.

SurferTim,

How are you determining it is not responding to the connection requests?

-->By constantly monitoring all requests and responses.

There are 4 sockets, but the ethernet web server library code will service only one socket (connection) at a time. All other connections must wait their turn.

-->Lets say server.available is continuously called in the loop{} function. Lets say a request is made for image.jpg on socket 0 and 1 at the same time. The code for available() will continue to return a client on sock 0. If your able to complete the entire response for image.jpg in one code execution, this is not a problem. Generally, however, you will need to respond in multiple code execution cycles. In the meantime socket 1 is not being responded to. Not until the request and response is complete will the available function return a client on socket 1. In order to allow multiple simultaneous connections the first socket in the loop needs to iterated. I modified the code below to do this(not sure if it is the most efficient, but it does work).

So, instead of this:
0,1,2,3
0,1,2,3
0,1,2,3

it needs to go like this:
0,1,2,3
1,2,3,0
2,3,0,1
3,0,1,2

EthernetClient EthernetServer::available()
{
_startsock+=1; //set to 0 on server begin
if(_startsock==MAX_SOCK_NUM) _startsock=0;
int sock= _startsock;
accept();
for (int i=0; i<MAX_SOCK_NUM; i++) {
sock+=1;
if(sock==MAX_SOCK_NUM) sock=0;
EthernetClient client(sock);
......

I did not say "not responding". I said the other sockets (connections) must wait their turn. All the successful connections received a response.

The w5100 accepts the first 4 requests. It responds to only one request at a time. I have performed a couple tests using multiple computers and both tests worked exactly as I predicted. Others have performed virtually the same test using multiple instances of programs to saturate the w5100, and all worked well according to the testers.

I used three computers on the last test. All three would show connected, but only one was receiving data at a time. It would service each in turn.

I'm not certain what you mean by "one code execution". Mine serviced one client request in one iteration of the loop() routine. Three client requests, three iterations of the loop().

edit: If a client needs more than one file, those requests must be made individually. Some web browsers will send a request for Favicon.ico after every request. That is one client but two client requests using two sockets and two iterations through loop().

SurferTim,

I did some testing, this doesn't appear to be an issue for me anymore(I no longer need the EthernetServer::available edits noted previously), however I do think there could be issues depending on input and connection type. It is a matter of receiving the request as soon as possible and responding to each of those requests a little bit at a time. By responding to each request a little bit at a time it allows the server to be more responsive.

Thanks,

-diesel

It is a matter of receiving the request as soon as possible and responding to each of those requests a little bit at a time. By responding to each request a little bit at a time it allows the server to be more responsive.

I don't believe that would be the case. If you service one connection completely, you can take another connection. To me, that is more responsive. Otherwise, you cannot take another new connection until you finish servicing at least one of the current connections.

And the complexity and memory requirements of remembering where you are with each connection may not be practical with a small processor like the Arduino. Even the Mega 2560 may have trouble with that.