Connection Refused: W5500 Ethernet Shield on Metro M4

I’ve written a web server that I’ve been testing and adding to for weeks. I notice that it sometimes refuses a browser connection request. I’ve identified 2 test cases that make this happen.

  1. If I load a test HTML page containing 3 image tags referring to images on the server, the connection request for the 3rd image almost is always refused. The files in question are 156K, 77K and 44K in size, with the last one being the smallest. If I rearrange them so the large one is the last one on the page, they all load reliably.

  2. If I load a page that requires the server to deliver both a javascript file and an associated css file, the 2nd connection is refused unless I put one at the top of the header and the other at the end.

My first thought was that I was running out of sockets, though it was hard to see how that could happen when the W5500 supports 8 concurrent sockets. So I debugged it and was surprised to find that the Ethernet library sets MAX_SOCK_NUM to 4 instead of 8, presumably in Ethernet.h:

//#if defined(RAMEND) && defined(RAMSTART) && ((RAMEND - RAMSTART) <= 2048)
//#define MAX_SOCK_NUM 4
#define MAX_SOCK_NUM 8

I searched my entire source code tree for “RAMEND” and found it only in Ethernet.h; apparently the 4 socket limit is caused by the lack of a definition for it. So I commented out the compile-time logic and see in the debugger that the library now allocates 8 sockets but I still get the Connection Refused error in both test cases described above. My target platform, the Metro M4, has 192K of RAM of which I’m using about 9K).

I’m using the latest Ethernet lib, released at the end of July 2019 that supports W5100, W5200 and W5500 in one lib.

Any thoughts about the likely cause or how to hunt it down?

Solved. Improper handling of "Connection: keep-alive" header request from client caused the use of more sockets than was necessary. Fixed it and now when I monitor chrome://net-internals/#sockets during page loading I see no more than 3 sockets open at any given time.

I'd still like to know where "RAMEND" and "RAMSTART" should be defined and why they're not, though.