Hello,
SDLNet_TCP_Recv() and SDLNet_UDP_Recv() do exactly that.
Well, UDP, sure, but I actually want guaranteed and in-order delivery,
so I’d like to use TCP.
Well, the documentation is confusing I think. From the
SDLNet_TCP_Recv() docs…
Receive data of exactly length maxlen bytes from the socket sock, into
the memory pointed to by data.
This routine is not used for server sockets.
Unless there is an error, or the connection is closed, the buffer will
read maxlen bytes. If you read more than is sent from the other end,
then it will wait until the full requested length is sent, or until the
connection is closed from the other end.
This makes it sound like it will block until the buffer you give it is
full. I had to start digging in the source to realize that it will read
UP TO maxlen bytes, but will still return how much was read if the
buffer isn’t full.
This does not merely make it sound like it, it describes the “block til
full” behaviour precisely. I must confess that I now see I had misread
the code, probably due to reading the docs just before.
I think it means if you call recv and nothing is there to be read, it
will block until there is.
There’s that, plus sending will still block until everything is sent.
Blocking until a buffer is filled doesn’t seem entirely useful to me.
Actually, it is useful (provided you know the length of the “message”,
which is often the case) in the context of the simple “receive request,
then send reply” server model. You know the one, where every new
connecting client spawns a new thread or fork.
In fact, the “block until fully completed” model is exactly what someone
new to networking will expect, and will eventually trip over if it’s
missing. That’s why I assumed the docs were correct, to make networking
"just work".
I seem to have not made it clear what my requirements were, and why the
present code is still not sufficient. Here’s what I want:
- I’d like to not have to use threads or any callback or event model.
Bob had pointed me towards his NET2 code, and it looks very good, but an
early design choice of mine (for code readability) was to not use
threads or callbacks for my current project.
- SDLNet_TCP_Send, as it is, will block until everything is sent. With
CheckSockets, I can check whether the first (internal) send will block
or not, but not the whole Send. I’d like Send to return the number of
bytes sent, including a value lower than len if not all could be sent on
the first try, or 0 if the call would block in any case.
- Likewise, SDLNet_TCP_Recv will still block until it can return that it
read more than 0 bytes. I’d like it to return 0 instead of blocking.
Yes, CheckSockets can help here, but it encumbers the interface too much
for my liking.
So I think I’ll try adapting SDL_Net myself. It shouldn’t take more than
a “blocking” flag, adding “O_NONBLOCK” to all sockets, and changing the
do {
send_or_read();
} while (!sent_or_read_enough)
parts, for Linux anyway. I’ll let you know how it turned out.
Thanks everyone!
Benjamin