问题
Why doesn't the recv
system call just block until all the data is received? Every time I have seen a recv
call, it's in a while loop which just keeps on calling recv
until all the data is there. Why not just have recv
block in the first place?
回答1:
You can request that recv block until all data is received, with the MSG_WAITALL
flag. However, if a signal arrives, a system call that has performed some work (ie, receiving part of the data) cannot be automatically restarted to receive the rest. As such, even with MSG_WAITALL
, there are cases where the recv call may return before the buffer is full, and you must be prepared to handle these cases. Given this, many people simply choose to loop and not bother with little-known flags such as MSG_WAITALL
.
As for why this is the case by default, there are a few reasons that come to mind:
- Frequently you want to receive partial reads. For example, if you're incrementally displaying the data as it comes in, or if you're proxying it to somewhere else, or if the data is just so large you can't buffer the whole thing in memory at once. After all, if you're just immediately writing to a file, do you care that you split it across 200 writes instead of, say, 150?
- Sometimes you don't even know how much data you need at the start. Consider the
telnet
protocol, which was popular around the time when the BSD sockets API was designed. You'll typically be receiving a handful of bytes at a time, there are no length fields telling you how much data to expect, and moreover you need to display that data right away. It doesn't make sense to block until you fill a buffer here. Likewise with line-oriented protocols such as SMTP or IMAP - you don't know how long the command is until you've received all of it. recv
is often used for datagram sockets, where it receives a single datagram, even if it's much smaller than the buffer provided. The natural extension to streaming sockets is to just return as much as you can without waiting.
But most importantly, since you need to be prepared to deal with a partial buffer anyway, it's good to force people to deal with it by default, so they turn up the bugs in their loop early - rather than having them remain hiding until a signal arrives at an unfortunate moment.
回答2:
In most cases, you don't know how much data is "all of the data". For example, if you're receiving data in a line-oriented protocol, a line might be 10 bytes long or 65 bytes long.
回答3:
You can change socket flags to either blocking or non-blocking. Your specific case actually has nothing to do with blocking or not blocking.
It would make no sense to make a network function behave in the way you describe by default - what if the stream never ends .. should the program never end? Prima facia, this doesn't seem like healthy default behavior.
Read http://www.scottklement.com/rpg/socktut/nonblocking.html to familiarize yourself with blocking and non-blocking IO.
来源:https://stackoverflow.com/questions/8783578/why-doesnt-recv-block-until-it-receives-all-of-the-data