Check if data is available before using recv() - winsock

Is there a way you can use select() on an single socket, without involving fd_set?
I want to make sure there is something to read before using recv() so it doesn't block. Alternatively use recv() if it immediately can return when there is nothing to read in.

Unfortunately, no.
The only way to use select() without involving at least one fd_set is to supply 3 nullptrs (NULLs) to select which effectively turns the select call into a sleep using the timeout argument.

Related

Why would one need to use `MSG_WAITALL` FLAG instead of `0` FLAG? Why to use it with UDP?

At some point when coding sockets one will face the receive-family of functions (recv, recvfrom, recvmsg).
This function accepts a FLAG argument, in which I see that the MSG_WAITALL is used in many examples on the web, such as this example on UDP.
Here is a definition of the MSG_WAITALL flag
MSG_WAITALL (since Linux 2.2)
This flag requests that the operation block until the full request is satisfied. However, the call may still return less data than requested if a signal is caught, an error or disconnect occurs, or the next data to be received is of a different type than that returned. This flag has no effect for datagram sockets.
Hence, my two questions:
Why would one need to use MSG_WAITALL FLAG instead of 0 FLAG? (Could someone explain a scenario of a problem for which the use of this would be the solution?)
Why to use it with UDP?
As the quoted man page mentions, MSG_WAITALL has no effect on UDP sockets, so there's no reason to use it there. Examples that do use it are probably confused and/or the result of several generations of cargo-cult/copy-and-paste programming. :)
For TCP, OTOH, the default behavior of recv() is to block until at least one byte of data can be copied into the user's buffer from the sockets incoming-data-buffer. The TCP stack will try to provide as many bytes of data as it can, of course, but in a case where the socket's incoming-data-buffer contains fewer bytes of data than the user has passed in to recv(), the TCP stack will copy as many bytes as it can, and return the byte-count indicating how many bytes it actually provided.
However, some people find would prefer to have their recv() call keep blocking until all of the bytes in their passed-in array have been filled in, regardless of how long that might take. For those people, the MSG_WAITALL flag provides a simple way to obtain that behavior. (The flag is not strictly necessary, since the programmer could always emulate that behavior by writing a while() loop that calls recv() multiple times as necessary, until all the bytes in the buffer have been populated... but it's provided as a convenience nonetheless)

How can I check if reading from a tcp socket will block?

If I have a tcp connection conn, how can determine whether conn.Read will block?
My understanding is that Go's Read uses non-blocking sockets and will only block if there's no data available to read (See https://stackoverflow.com/a/36117724/4447365).
But is there any way to check if the socket has no data available?
This can be done with the POSIX read function by calling it with a count argument of zero.
When programming in Go don't worry about it. Assume everything will block. Then put it in a goroutine so it runs asynchronously anyway.
The Go runtime handles all of the details.
Also, the issue here seems to be what you want to do. The issue was rejected: Go doesn't do that. Neither does C. And even if it did it isn't reliable. If you read down to the end there are suggested solutions involving the Linger TCP setting.

Mechanism of MSG_WAITALL in Berkeley socket

In Berkeley socket, is recv function with MSG_WAITALL flag set, replaces having multiple read functions until the the whole data requested has been read?
I mean does recv function read the whole block determined by the size in one call, whereas the the read function might read part of the data block, and I need to call it multiple times in a loop until the whole block is read?
Yes, MSG_WAITALL tells recv() to wait until all of the requested bytes have been read. However, that it is only supported in blocking mode and not in non-blocking mode, and it only works on stream-oriented sockets, like TCP. Even then, you also still have to loop, such as on Linux if recv() gets interrupted by a signal and has to be called again to continue reading.

the function select() for multi client socket programming

I have simple question about select() of I/O multiplexing function for socket programming.
When select function executes, it`s said that it modifies its examining fd set,
so we need to reset it again every time.
(fd_set read_fds for example..)
But why is that?
Why does the select function clears the uninteresting file descriptors on its fd sets?
What changes select function give to (or modify) original fd set?
Thanks.
all I found from book or somewhere else on web says
'We need to' reset for every loop routine but it doesn`t say how it is.
Why does the select function clears the uninteresting file descriptors
on its fd sets?
Because after select() returns, you're (presumably) going to want to query (via FD_ISSET()) which socket(s) are now ready-for-read (or ready-for-write).
So when select() returns, it modifies the fd_set objects so that the only bits still set inside them are the bits representing sockets that are now ready. If it did not do that, FD_ISSET() would have no way to know which sockets are ready for use and which are not.

using select in winsock2

I'm trying to get select to work right and it seems to be returning 1 even when there is nothing to be read on the socket. So I end up calling recv and it blocks because nothing is there to read.
Also annoying is the fact that with winsock it is necessary to call FD_SET each time select is called, which isn't consistent with standard implementations.
Are there any other weird quirks I need to be aware of?
I fixed it but I cannot determine what exactly the cause of the problem was. I do know that it is very relevant that FD_SET must be used to re-set the set for each select() call. According to the documentation, after calling select it fills in the sets which are ready for read/write/etc.
Moral of the story today is: read the documentation.