Reputation: 639
I am writing a simple TCP server, and despite a lot of Googling I can't quite figure out the answer to a question of mine.
I want my server to handle multiple clients.
For performance and simplicity reasons, I want my server to be single-threaded, and I use select()
to handle all the sockets.
Also, my protocol is message-based. Message framing is done using a length prefix. This means the server needs a buffer to reconstruct messages fragment after fragment.
The maximum message length is 64K bytes (although I could reduce it to 256 bytes).
Note: this will run on a tiny embedded device, so using a messaging layer like ZMQ is not an option (not enough memory).
I can either:
have a single buffer, but it means once I started to receive/reconstruct a message from a client socket, I ignore other client sockets until the current message has been completely received. This is prone to DOS attacks: one client sending a huge message, byte per byte, very slowly, would block the server.
have one buffer per client socket, and then my server would be really parallel. But it does not scale well with the number of clients.
Is there another way which has the benefits of both techniques and none of the drawbacks?
One idea I had was to use the socket buffer to store the entire message.
I would set the buffer size to 64K using setsockopt()
and SO_RCVBUFSIZ
.
But I would need to do a recv()
with both MSG_WAITALL
and MSG_DONTWAIT
, so that either the message is entirely available in the socket buffer and I get it, or it is not entirely received yet and then recv()
does not block. However, these 2 options do not work together.
Maybe I can do a recv()
with MSG_PEEK
to read the size, then another recv()
with MSG_PEEK
to test if all bytes are available, and if yes then re-do a recv()
without MSG_PEEK
to actually read the bytes from the socket?
Anyway, I have the impression it is a trivial question that must have been solved a long time ago.
Upvotes: 1
Views: 743
Reputation: 639
I found this series of blog which I find very clear and answered all my questions: https://eli.thegreenplace.net/2017/concurrent-servers-part-1-introduction/
Upvotes: 1
Reputation: 5790
If you can have both, why not use both?
With a little management, you are able to serve some clients simultaneously and don't waste precious memory.
Upvotes: 2