|Important||This document may not represent best practices for current development, links to downloads and other resources may no longer be valid. Current recommended version can be found here.|
A CFile object used for sending and receiving data across a network via Windows Sockets.
You can attach the CSocketFile object to a CSocket object for this purpose. You also can, and usually do, attach the CSocketFile object to a CArchive object to simplify sending and receiving data using MFC serialization.
To serialize (send) data, you insert it into the archive, which calls CSocketFile member functions to write data to the CSocket object. To deserialize (receive) data, you extract from the archive. This causes the archive to call CSocketFile member functions to read data from the CSocket object.
Besides using CSocketFile as described here, you can use it as a stand-alone file object, just as you can with CFile, its base class. You can also use CSocketFile with any archive-based MFC serialization functions. Because CSocketFile does not support all of CFile's functionality, some default MFC serialize functions are not compatible with CSocketFile. This is particularly true of the CEditView class. You should not try to serialize CEditView data through a CArchive object attached to a CSocketFile object using CEditView::SerializeRaw; use CEditView::Serialize instead. The SerializeRaw function expects the file object to have functions, such as Seek, that CSocketFile does not have.
When you use CArchive with CSocketFile and CSocket, you might encounter a situation where CSocket::Receive enters a loop (by PumpMessages(FD_READ)) waiting for the requested amount of bytes. This is because Windows sockets allow only one recv call per FD_READ notification, but CSocketFile and CSocket allow multiple recv calls per FD_READ. If you get an FD_READ when there is no data to read, the application hangs. If you never get another FD_READ, the application stops communicating over the socket.
You can resolve this problem as follows. In the OnReceive method of your socket class, call CAsyncSocket::IOCtl(FIONREAD, ...) before you call the Serialize method of your message class when the expected data to be read from the socket exceeds the size of one TCP packet (maximum transmission unit of the network medium, usually at least 1096 bytes). If the size of the available data is less than needed, wait for all the data to be received and only then start the read operation.
In the following example, m_dwExpected is the approximate number of bytes that the user expects to receive. It is assumed that you declare it elsewhere in your code.