Discussion:
Socket limits
(too old to reply)
Alan Adams
2020-04-20 18:25:06 UTC
Permalink
Hi

I'm using all this free time to work on my slalom competition scoring
system. It consists of a database server and a significant number of
client applications, running anyt=where on a local network of RISC OS
computers, mostly RPIs. The connections between them use TCP/IP.

I'm stress testing the system at the moment by running the maximum number
of clients. In addition to exposing several latent bugs, that only get hit
very infrequently, it has shown up limits in a couple of pieces of
software that aren't mine. A couple of my bugs showed up after a 2 hour
run with the maximum number of clients on the network. The last 3 days
have been spent finding more quickly reproducable ways to trigger them, so
that I could find out what was happening. (It turned out all to be
problems reading data around the wrap in a ring buffer.)

I use SocketWatch to monitor incoming sockets and return poll reason 13 -
pollword non-zero, in order to get the data read quickly. SocketWatch uses
a bitmap to identify the sockets, and it's a 32-bit integer, meaning I can
only monitor 32 sockets. This in turn limits the server to 28 clients, as
4 bits are already in use. (The hardware timing system uses two to
indicate that GPIO events have taken place, and there's a couple of others
already tied up.)

Each client has 3 sockets - one to broadcast a request for the server, one
to listen to incoming data, and one to send data to the server. The server
uses one broadcast, and one listen, plus one send socket per client.
Running all this on one machine, as I have been doing in testing, can tie
up 112 sockets. I also have Hermes and Messenger Pro running, plus
shareFS, and those together use the first 10 sockets.

It turns out Hermes and NewsHound both create a socket when they fetch,
and delete it afterwards. This fails if socket number 95 is already in
use, so I assume they are written with data allocated for handling 96
sockets.

I think I can reduce my socket usage by creating the broadcast sockets
when needed and deleting them afterwards. That will need some testing of
course. It's not just the initial connection that uses them - if a
connection drops or times out, the system attempts to reconnect
automatically.
--
Alan Adams, from Northamptonshire
***@adamshome.org.uk
http://www.nckc.org.uk/
Paolo Fabio Zaino
2020-04-20 23:03:13 UTC
Permalink
Post by Alan Adams
Hi
I'm using all this free time to work on my slalom competition scoring
system. It consists of a database server and a significant number of
client applications, running anyt=where on a local network of RISC OS
computers, mostly RPIs. The connections between them use TCP/IP.
I'm stress testing the system at the moment by running the maximum number
of clients. In addition to exposing several latent bugs, that only get hit
very infrequently, it has shown up limits in a couple of pieces of
software that aren't mine. A couple of my bugs showed up after a 2 hour
run with the maximum number of clients on the network. The last 3 days
have been spent finding more quickly reproducable ways to trigger them, so
that I could find out what was happening. (It turned out all to be
problems reading data around the wrap in a ring buffer.)
I use SocketWatch to monitor incoming sockets and return poll reason 13 -
pollword non-zero, in order to get the data read quickly. SocketWatch uses
a bitmap to identify the sockets, and it's a 32-bit integer, meaning I can
only monitor 32 sockets. This in turn limits the server to 28 clients, as
4 bits are already in use. (The hardware timing system uses two to
indicate that GPIO events have taken place, and there's a couple of others
already tied up.)
Each client has 3 sockets - one to broadcast a request for the server, one
to listen to incoming data, and one to send data to the server. The server
uses one broadcast, and one listen, plus one send socket per client.
Running all this on one machine, as I have been doing in testing, can tie
up 112 sockets. I also have Hermes and Messenger Pro running, plus
shareFS, and those together use the first 10 sockets.
It turns out Hermes and NewsHound both create a socket when they fetch,
and delete it afterwards. This fails if socket number 95 is already in
use, so I assume they are written with data allocated for handling 96
sockets.
I think I can reduce my socket usage by creating the broadcast sockets
when needed and deleting them afterwards. That will need some testing of
course. It's not just the initial connection that uses them - if a
connection drops or times out, the system attempts to reconnect
automatically.
--
Alan Adams, from Northamptonshire
http://www.nckc.org.uk/
Hi Allan,
I can confirm that the maximum number of concurrent sockets at the moment available on RISC OS (any release) is 96.

I tested this not too long ago with a simple C code that opens them on a local machine until the OS refuses to open more and the number turn out to be 96.

After some investigation I have found this number is hardcoded in the OS Kernel source and it's so because of certain limitations related to the maximum number of files that can be opened together and how they are represented in the kernel (max number should be 256).

The specific define should be SOCKTABSIZE (if i remember well). You can also measure what's available calling SWI Socket_Getsize.

Basically on RISC OS sockets are in a distinct number space to file handles. Old programs may assume that file handles is an 8bit value (hence the 256) and so the limitation inherited by SOCKTABSIZE.

So I'm afraid to make it to work you'll have to stick to probably max 94/95 sockets and if you want to use all 96 make sure nothing else is running on your RPi (not even OmniClient etc.)

My 0.5c here, hope this helps,
- Paolo
druck
2020-04-20 23:59:44 UTC
Permalink
Post by Alan Adams
Each client has 3 sockets - one to broadcast a request for the server, one
to listen to incoming data, and one to send data to the server. The server
uses one broadcast, and one listen, plus one send socket per client.
[Snip]

Why do you need a send and receive socket? A single TCP socket can do
both, you can even send out of band data to implement asynchronous
notifications.
Post by Alan Adams
I think I can reduce my socket usage by creating the broadcast sockets
when needed and deleting them afterwards. That will need some testing of
course. It's not just the initial connection that uses them - if a
connection drops or times out, the system attempts to reconnect
automatically.
The clients broadcast socket can be created only when needed. Once
you've sent a broadcast to identify the server, you should be able to
reconnect to the same address after that.

If you really need more clients, consider switching to UDP rather than
TCP, as the sever can receive data from any number of clients on a
single socket. You can chuck around far more data with UDP, but you have
to take care of the integrity yourself.

---druck
Alan Adams
2020-04-21 14:39:45 UTC
Permalink
Post by druck
Post by Alan Adams
Each client has 3 sockets - one to broadcast a request for the server, one
to listen to incoming data, and one to send data to the server. The server
uses one broadcast, and one listen, plus one send socket per client.
[Snip]
Why do you need a send and receive socket? A single TCP socket can do
both, you can even send out of band data to implement asynchronous
notifications.
Thanks for the comments. It's helped me clarify what actually happens.

I've just trawled my way through the part of the code I wrote about ten
years ago to handle connections.

The listen socket listens for broadcast data. Not all of the applications
need it, so there's one easy saving I can make.

It's used for those applications where there must not be two copies
running anywhere across the network. When one of those starts up it
broadcasts a message effectively sayinf "are you there". Any pre-existing
copy will reply. If the new copy wants to take over, it sends a "quit"
message to the earlier copy, which shuts down. This allows control to be
passed to a different computer for example.
If it doesn't want to take over, it simply quits.
Post by druck
Post by Alan Adams
I think I can reduce my socket usage by creating the broadcast sockets
when needed and deleting them afterwards. That will need some testing of
course. It's not just the initial connection that uses them - if a
connection drops or times out, the system attempts to reconnect
automatically.
The clients broadcast socket can be created only when needed. Once
you've sent a broadcast to identify the server, you should be able to
reconnect to the same address after that.
I think it will be fairly easy to create the broadcast socket as needed. I
just need to check how easy it is to delete it cleanly after use.
Alternatively I think I would need to record the server address and
listen-port number to send the announcement that starts the reconnection.

I'm now at a good point to look at these changes, as I've eliminated a
long-standing bug that, at apparently random times, caused a disconnection
followed by an inability to reconnect. It came down to the difference
betweeen IF K%<0 and IF K%<=0.
Post by druck
If you really need more clients, consider switching to UDP rather than
TCP, as the sever can receive data from any number of clients on a
single socket. You can chuck around far more data with UDP, but you have
to take care of the integrity yourself.
I've had another look at socketwatch, and I don't think I need a separate
bit in the mask for each client. That seems to be used to allow the poll
return to identify quickly which socket needs servicing. I'm scanning them
all, so it shouldn't be needed.

In normal use, I expect to need somewhere just over 20 clients across the
network at a time. The socketwatch limitation I thought existed, would
have made that a bit marginal.

The socket limit of 96 would only apply in the unusual case of running all
the clients on one computer. This would only occur during testing.
Post by druck
---druck
--
Alan Adams, from Northamptonshire
***@adamshome.org.uk
http://www.nckc.org.uk/
Alan Adams
2020-04-22 11:59:55 UTC
Permalink
Post by druck
Post by Alan Adams
Each client has 3 sockets - one to broadcast a request for the server, one
to listen to incoming data, and one to send data to the server. The server
uses one broadcast, and one listen, plus one send socket per client.
<SNIP>

I've now eliminated the unnecessary listen sockets.
Post by druck
Post by Alan Adams
I think I can reduce my socket usage by creating the broadcast sockets
when needed and deleting them afterwards. That will need some testing of
course. It's not just the initial connection that uses them - if a
connection drops or times out, the system attempts to reconnect
automatically.
The clients broadcast socket can be created only when needed. Once
you've sent a broadcast to identify the server, you should be able to
reconnect to the same address after that.
I've tried deferering the creation of the broadcast socket until it's
needed, and i can't get it to work. Odd, because I'm using the same code,
just called at a different place.

I've tried running it on a different computer from the server and I can
see packets going through the switch, but the server doesn't record
anything as received.

The sender is saying the port and socket are the same as in the working
version, so I don't quite know what to look for next.

I guess my next step will be Wiresalmon and see what the packets actually
contain.
Post by druck
---druck
--
Alan Adams, from Northamptonshire
***@adamshome.org.uk
http://www.nckc.org.uk/
Loading...