Сокеты Windows. Работа сокетов с архивами

В этой статье объясняется, как объект CSocket, объект CSocketFile и объект CArchive объединяются для упрощения отправки и получения данных через сокет Windows.

В статье Windows Sockets: Пример сокетов с помощью архивов представляет функцию PacketSerialize . Объект архива в PacketSerialize примере работает так же, как архивный объект, переданный в функцию сериализации MFC. Важное отличие заключается в том, что для сокетов архив присоединяется не к стандартному объекту CFile (обычно связанному с файлом диска), но к объекту CSocketFile . Вместо подключения к файлу CSocketFile диска объект подключается к объекту CSocket .

Объект CArchive управляет буфером. Когда буфер архива хранения (отправки) заполнен, связанный CFile объект записывает содержимое буфера. Очистка буфера архива, подключенного к сокету, эквивалентна отправке сообщения. Когда буфер архива загрузки (получения) заполнен, объект перестает считывать, CFile пока буфер не будет доступен снова.

Класс CSocketFile является производным отCFile, но не поддерживает функции-члены CFile, такие как функции размещения (Seek,, SetLengthGetLengthи т. д.), функции блокировки (LockRange, UnlockRangeили GetPosition функция). Весь объект CSocketFile должен выполнять запись или чтение последовательностей байтов в связанный объект или из негоCSocket. Так как файл не участвует, такие операции, как Seek и GetPosition не имеет смысла. CSocketFile является производным от CFile, поэтому обычно он наследует все эти функции-члены. Чтобы предотвратить это, неподдерживаемые CFile функции-члены переопределяются для CSocketFile создания CNotSupportedException.

Объект CSocketFile вызывает функции-члены объекта CSocket для отправки или получения данных.

На следующем рисунке показаны связи между этими объектами на обеих сторонах связи.

CArchive, CSocketFile, and CSocket.
CArchive, CSocketFile и CSocket

Цель этой очевидной сложности заключается в том, чтобы защитить вас от необходимости управлять деталями сокета самостоятельно. Вы создаете сокет, файл и архив, а затем начинаете отправлять или получать данные, вставляя их в архив или извлекая их из архива. CArchive, CSocketFile и CSocket управляют сведениями за кулисами.

Объект CSocket на самом деле является двухфакторным объектом: иногда асинхронным (обычным состоянием) и иногда синхронным. В асинхронном состоянии сокет может получать асинхронные уведомления из платформы. Однако во время операции, такой как получение или отправка данных, сокет становится синхронным. Это означает, что сокет не получит дополнительных асинхронных уведомлений до завершения синхронной операции. Так как он переключает режимы, можно, например, сделать следующее:

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

      ar >> str;
   }
}

Если CSocket он не реализован как объект с двумя состояниями, то при обработке предыдущего уведомления можно получить дополнительные уведомления для того же типа события. Например, при обработке OnReceiveOnReceiveможет появиться уведомление. В приведенном выше фрагменте кода извлечение str из архива может привести к рекурсии. Переключение состояний предотвращает рекурсию, CSocket предотвращая дополнительные уведомления. Общее правило не является уведомлениями в уведомлениях.

Примечание.

Можно CSocketFile также использовать в качестве (ограниченного CArchive ) файла без объекта. По умолчанию CSocketFile параметр bArchiveCompatible конструктора имеет значение TRUE. Это указывает, что объект файла предназначен для использования с архивом. Чтобы использовать объект файла без архива, передайте значение FALSE в параметре bArchiveCompatible .

В режиме "совместимого с архивом" CSocketFile объект обеспечивает более высокую производительность и снижает опасность "взаимоблокировки". Взаимоблокировка возникает, когда отправка и получение сокетов ожидают друг друга или ожидают общего ресурса. Эта ситуация может произойти, если CArchive объект работал с CSocketFile тем, как он выполняется с CFile объектом. С помощью CFileархива можно предположить, что если он получает меньше байтов, чем запрошено, то достигнут конец файла. Однако данные CSocketFileоснованы на сообщениях; буфер может содержать несколько сообщений, поэтому получение меньше количества запрошенных байтов не означает конец файла. Приложение не блокируется в этом случае, так как оно может использовать CFile, и оно может продолжать чтение сообщений из буфера до тех пор, пока буфер не будет пуст. Функция CArchive IsBufferEmpty полезна для мониторинга состояния буфера архива в таком случае.

Дополнительные сведения см. в статье "Сокеты Windows: использование сокетов с архивами"

См. также

Сокеты Windows в MFC
CObject::Serialize