Сокеты Windows. Работа сокетов с архивамиWindows Sockets: How Sockets with Archives Work

В этой статье объясняется, как объединяются объект CSocket , объект CSocketFile и объект CArchive , чтобы упростить отправку и получение данных через сокет Windows.This article explains how a CSocket object, a CSocketFile object, and a CArchive object are combined to simplify sending and receiving data through a Windows Socket.

В статье сокеты Windows: пример сокетов, использующих архивы , представляет PacketSerialize функцию.The article Windows Sockets: Example of Sockets Using Archives presents the PacketSerialize function. Объект архива в этом PacketSerialize примере работает во многом подобно архивному объекту, переданному в функцию сериализации MFC.The archive object in the PacketSerialize example works much like an archive object passed to an MFC Serialize function. Важное отличие заключается в том, что для сокетов Архив прикрепляется не к стандартному объекту кфиле (обычно связанному с дискового файла), а к CSocketFile объекту.The essential difference is that for sockets, the archive is attached not to a standard CFile object (typically associated with a disk file) but to a CSocketFile object. Вместо соединения с дискового файла CSocketFile объект подключается к CSocket объекту.Rather than connecting to a disk file, the CSocketFile object connects to a CSocket object.

CArchiveОбъект управляет буфером.A CArchive object manages a buffer. При заполнении буфера хранения архива (отправка) связанный CFile объект записывает содержимое буфера.When the buffer of a storing (sending) archive is full, an associated CFile object writes out the buffer's contents. Очистка буфера архива, подключенного к сокету, эквивалентна отправке сообщения.Flushing the buffer of an archive attached to a socket is equivalent to sending a message. Когда буфер архива (получение) заполнен, CFile объект прекращает чтение, пока буфер не будет снова доступен.When the buffer of a loading (receiving) archive is full, the CFile object stops reading until the buffer is available again.

Класс CSocketFile является производным от CFile , но не поддерживает функции-члены кфиле , такие как функции позиционирования ( Seek , GetLength , SetLength и т. д.), функции блокировки ( LockRange , UnlockRange ) или GetPosition функции.Class CSocketFile derives from CFile, but it does not support CFile member functions such as the positioning functions (Seek, GetLength, SetLength, and so on), the locking functions (LockRange, UnlockRange), or the GetPosition function. Все объекты CSocketFile должны выполнять запись или чтение последовательности байтов в связанный объект или из него CSocket .All the CSocketFile object must do is write or read sequences of bytes to or from the associated CSocket object. Поскольку файл не участвует в работе, такие операции, как и, не имеют Seek GetPosition смысла.Because a file is not involved, operations such as Seek and GetPosition make no sense. CSocketFile является производным от CFile , поэтому он обычно наследует все эти функции-члены.CSocketFile is derived from CFile, so it would normally inherit all of these member functions. Чтобы избежать этого, неподдерживаемые функции- CFile члены переопределяются в CSocketFile для создания кнотсуппортедексцептион.To prevent this, the unsupported CFile member functions are overridden in CSocketFile to throw a CNotSupportedException.

CSocketFileОбъект вызывает функции члена своего CSocket объекта для отправки или получения данных.The CSocketFile object calls member functions of its CSocket object to send or receive data.

На следующем рисунке показаны связи между этими объектами на обеих сторонах связи.The following figure shows the relationships among these objects on both sides of the communication.

CArchive, CSocketFile и CSocketCArchive, CSocketFile, and CSocket
CArchive, CSocketFile и CSocketCArchive, CSocketFile, and CSocket

Эта очевидная сложность заключается в том, чтобы защитить вас от необходимости самостоятельно управлять сведениями о сокете.The purpose of this apparent complexity is to shield you from the necessity of managing the details of the socket yourself. Вы создадите сокет, файл и архив, а затем начнете отправлять или получать данные, вставив их в архив или извлекая из архива.You create the socket, the file, and the archive, and then begin sending or receiving data by inserting it to the archive or extracting it from the archive. CArchive, CSocketFileи CSocket управляют деталями в фоновом режиме.CArchive, CSocketFile, and CSocket manage the details behind the scenes.

CSocketОбъект на самом деле является объектом с двумя состояниями: иногда асинхронным (обычное состояние) и иногда синхронным.A CSocket object is actually a two-state object: sometimes asynchronous (the usual state) and sometimes synchronous. В асинхронном состоянии сокет может получать асинхронные уведомления от платформы.In its asynchronous state, a socket can receive asynchronous notifications from the framework. Однако во время таких операций, как получение или отправка данных, сокет получает синхронный режим.However, during an operation such as receiving or sending data the socket becomes synchronous. Это означает, что сокет не будет получать дополнительные асинхронные уведомления, пока не завершится синхронная операция.This means the socket will receive no further asynchronous notifications until the synchronous operation has completed. Так как он переключает режимы, можно, например, сделать что-то вроде следующего:Because it switches modes, you can, for example, do something like the following:

void CMySocket::OnReceive(int nErrorCode)
{
   if (0 == nErrorCode)
   {
      CSocketFile file(this);
      CArchive ar(&file, CArchive::load);
      CString str;

      ar >> str;
   }
}

Если CSocket не были реализованы в виде объекта с двумя состояниями, при обработке предыдущего уведомления может быть возможно получение дополнительных уведомлений для одного и того же вида событий.If CSocket were not implemented as a two-state object, it might be possible to receive additional notifications for the same kind of event while you were processing a previous notification. Например, при обработке объекта может появиться OnReceive уведомление OnReceive .For example, you might get an OnReceive notification while processing an OnReceive. В приведенном выше фрагменте кода извлечение str из архива может привести к рекурсии.In the code fragment above, extracting str from the archive might lead to recursion. При переключении состояний CSocket предотвращается рекурсия, препятствуя дополнительным уведомлениям.By switching states, CSocket prevents recursion by preventing additional notifications. Общее правило не является уведомлениями в уведомлениях.The general rule is no notifications within notifications.

Примечание

CSocketFileТакже можно использовать в качестве файла (с ограниченным доступом) без CArchive объекта.A CSocketFile can also be used as a (limited) file without a CArchive object. По умолчанию CSocketFile параметр барчивекомпатибле конструктора имеет значение true.By default, the CSocketFile constructor's bArchiveCompatible parameter is TRUE. Указывает, что файловый объект предназначен для использования с архивом.This specifies that the file object is for use with an archive. Чтобы использовать объект File без архива, передайте значение false в параметре барчивекомпатибле .To use the file object without an archive, pass FALSE in the bArchiveCompatible parameter.

В режиме «архивный» CSocketFile объект обеспечивает лучшую производительность и снижает опасность «взаимоблокировки».In its "archive compatible" mode, a CSocketFile object provides better performance and reduces the danger of a "deadlock." Взаимоблокировка возникает, когда оба приема сокетов ожидают друг друга или ожидают общий ресурс.A deadlock occurs when both the sending and receiving sockets are waiting on each other, or waiting for a common resource. Такая ситуация может возникнуть, если CArchive объект работал так же, CSocketFile как и CFile объект.This situation might occur if the CArchive object worked with the CSocketFile the way it does with a CFile object. С помощью CFile архива можно предположить, что при получении меньшего количества байтов, чем запрошено, достигнут конец файла.With CFile, the archive can assume that if it receives fewer bytes than it requested, the end of file has been reached. CSocketFileТем не менее, данные основаны на сообщениях; буфер может содержать несколько сообщений, поэтому получение меньшего числа запрошенных байтов не подразумевает конца файла.With CSocketFile, however, data is message based; the buffer can contain multiple messages, so receiving fewer than the number of bytes requested does not imply end of file. Приложение не блокируется в этом случае, как это возможно CFile , и может продолжать чтение сообщений из буфера до тех пор, пока буфер не будет пустым.The application does not block in this case as it might with CFile, and it can continue reading messages from the buffer until the buffer is empty. Функция исбуфферемпти в полезна CArchive для мониторинга состояния буфера архива в таком случае.The IsBufferEmpty function in CArchive is useful for monitoring the state of the archive's buffer in such a case.

Дополнительные сведения см. в разделе сокеты Windows: Использование сокетов с архивамиFor more information, see Windows Sockets: Using Sockets with Archives

См. также разделSee also

Сокеты Windows в MFCWindows Sockets in MFC
CObject:: SerializeCObject::Serialize