INFO: Avoid Data Peeking in Winsock

Peeking for data in Winsock means that an application requests for theamount of incoming data waiting to be received without actually receivingit. This is a holdover from Winsock 1.1 compatibility with Unix BSDSockets. In Winsock, this is accomplished with either recv/WSARecv(...,MSG_PEEK) or ioctlsocket(FIONREAD, ...). You should avoid doing thisbecause it is highly inefficient, and it subjects an application to anincorrect data count.
More information
Socket implementation relies on fixed-size internal send and receivebuffers that are allocated as necessary from contiguous, non-paged poolmemory. The default size of these buffers is 8k each. Incoming network datais placed into the internal receive buffer for the socket.

Winsock applications that use one of the peek methods, with eitherrecv/WSARecv(..., MSG_PEEK) or ioctlsocket(FIONREAD, ...), to obtain theamount of data in the receive buffer is highly inefficient because thesystem must lock the data and count it. As the system does this, it islikely that the real-time network will still attempt to fill the bufferwith more data. Peeking also does not remove the data, which would allowthe buffer to reach its storage limit. As a result, this closes down thenetwork data-flow rate and makes the entire process of data transmissioninefficient.

Polling on a stream socket until a certain number of bytes or a "message"arrives is bad code. A stream socket, such as TCP, does not preservemessage boundaries because it provides a data stream. As such, the largestmessage size an application can ever depend upon is one-byte in length.Code that uses peeking to wait until a complete "message" arrives mightnever succeed on stream-based protocols in Winsock where the data straddlesmultiple system buffer boundaries, due to design decisions. The peekoperation will report the number of bytes up until the first bufferboundary. The bytes remaining in the other boundaries might never bereported, resulting in an incorrect count of data for code algorithms thatdepend upon the peek values to be accurate. Subsequent peek attempts willnot reveal the "hidden" data, which can still be received from the buffers.

The best stream-based protocol socket implementation is to drain dataimmediately upon arrival into application-allocated buffer space. Thisallows the socket buffers to remain open to a steady network data-flow rateas the application parses the data, resulting in much better networkperformance.
Windows Sockets 2 API Specification, Revision 2.2.0, May 10, 1996 AppendixC, "The Lame List", Item #20, #26.

For additional information, please see the following article in theMicrosoft Knowledge Base:
140263 PRB: recv() w/MSG_PEEK Always Returns Wrong Buffer Size

Article ID: 192599 - Last Review: 06/22/2014 19:15:00 - Revision: 3.0

  • kbapi kbinfo kbnetwork kbwinsock KB192599