FIX: Using CSocket w/ CArchive Causes Block from Extra FD_READ (138694)
The information in this article applies to:
- The Microsoft Foundation Classes (MFC), when used with:
- Microsoft Visual C++ for Windows, 16-bit edition 1.52
- Microsoft Visual C++, 32-bit Editions 2.1
- Microsoft Visual C++, 32-bit Editions 2.2
- Microsoft Visual C++, 32-bit Editions 4.0
- Microsoft Visual C++, 32-bit Editions 4.1
This article was previously published under Q138694 SYMPTOMS
Using a CArchive object with a CSocket can cause an extra FD_READ
notification to be posted when no data is pending. This happens when a
block of data is received through the extraction operator ('>>') or
CArchive::Read that is larger than the current buffer size of the CArchive
object.
This can cause OnReceive to be called when no data is present, which will
cause the application to hang indefinitely if a subsequent call to Receive
is made.
CAUSE
The CArchive class automatically buffers data reads and writes. If a call
is made to retrieve a block of data larger than the CArchive object's
buffer size, then the CArchive class will make two calls to retrieve the
data in buffer-size blocks.
When CSocket is used, the end result is two calls to the Receive function.
The first call to Receive does not retrieve all of the data currently in
the socket's buffer, so the Windows Sockets DLL posts an additional FD_READ
notification after this first call. Although the second call to Receive
might get the rest of the data from the buffer, the FD_READ notification
has already been posted and OnReceive will end up being called later even
though there is no data left to read on the socket.
RESOLUTION
Make sure there is data in the socket's buffer using CAsyncSocket::IOCtl()
before attempting to receive.
void CMySocket::OnReceive(int nErrorCode)
{
// TODO: Do some error handling on nErrorCode
DWORD dwBytes;
VERIFY(IOCtl(FIONREAD, &dwBytes));
if (0 == dwBytes) // if nothing to read, return
return;
do
{
// Read your data from your CArchive object
CString strData;
m_pMyArchive >> strData;
} while(!m_pMyArchive->IsBufferEmpty());
}
STATUS
Microsoft has confirmed this to be a bug in the Microsoft products listed
at the beginning of this article. This bug was fixed in Visual C++ version
4.2.
REFERENCES
Visual C++ Books On-line:
MFC Encyclopedia Articles:
"Windows Sockets: Using Sockets with Archives"
Win32 Programmer's Reference Documentation on the function:
WSAAsyncSelect
Modification Type: | Major | Last Reviewed: | 12/9/2003 |
---|
Keywords: | kbBug kbfix kbNoUpdate kbVC420fix kbWinsock KB138694 |
---|
|