Поделиться через


Отправка и получение данных PGM

Отправка и получение данных PGM аналогично отправке или получению данных на любом сокете. Существуют рекомендации, относящиеся к PGM, описанные в следующих абзацах.

Отправка данных PGM

После создания сеанса отправителя PGM данные отправляются с помощью различных функций отправки сокетов Windows: send, sendto, WSASendи WSASendTo. Так как дескриптор сокетов Windows — это дескриптор файловой системы, другие функции, такие как WriteFile и функции CRT, также могут передавать данные. В следующем фрагменте кода показана операция отправителя PGM:

LONG        error;
    //:
error = send (s, pSendBuffer, SendLength, 0);
if (error == SOCKET_ERROR)
{
    fprintf (stderr, "send() failed: Error = %d\n",
             WSAGetLastError());
}

При использовании режима сообщений (SOCK_RDM) каждый вызов функции отправки приводит к дискретному сообщению, что иногда бывает нежелательно; приложению может потребоваться отправить сообщение объемом 2 мегабайта с несколькими вызовами отправки . В таких случаях отправитель может задать параметр сокета RM_SET_MESSAGE_BOUNDARY, чтобы указать размер следующего сообщения.

Если окно отправки заполнено, новое сообщение из приложения не принимается, пока окно не будет расширено. Попытка отправки через неблокирующий сокет завершается ошибкой WSAEWOULDBLOCK; блокирующий сокет просто блокируется до тех пор, пока окно не достигнет той точки, где запрошенные данные можно будет буферизовать и отправить. В перекрывающихся ввода-выводах операция не завершается до тех пор, пока окно не будет достаточно, чтобы разместить новые данные.

Получение данных PGM

После создания сеанса приемника PGM данные получаются с помощью различных получающих функций Windows Sockets: recv, recvfrom, WSARecvи WSARecvFrom. Так как дескриптора сокетов Windows также являются дескрипторами файлов, функции readFile и CRT также можно использовать для получения данных сеанса PGM. Транспорт передает данные до получателя по мере их поступления, пока данные находятся в последовательности. Транспорт гарантирует, что возвращаемые данные являются непрерывными и не дублируются. В следующем фрагменте кода показана операция получения PGM:

LONG        BytesRead;
    //:
BytesRead = recv (sockR, pTestBuffer, MaxBufferSize, 0);
if (BytesRead == 0)
{
    fprintf(stdout, "Session was terminated\n");
}
else if (BytesRead == SOCKET_ERROR)
{
    fprintf(stderr, "recv() failed: Error = %d\n",
            WSAGetLastError());
}

При использовании режима передачи сообщений (SOCK_RDM), транспорт показывает, когда получено частичное сообщение, либо с ошибкой WSAEMSGSIZE, либо установив флаг MSG_PARTIAL при возврате из функций WSARecv и WSARecvFrom. Когда последний фрагмент полного сообщения возвращается клиенту, ошибка или флаг не указан.

Когда сеанс завершается корректно, операция приёма выдаёт ошибку WSAEDISCON. При потере данных в транспорте PGM временно буферизирует пакеты вне последовательности и пытается восстановить потерянные данные. Если потеря данных невосстановима, операция получения завершается с ошибкой WSAECONNRESET, и сеанс завершается. Сеанс можно сбросить из-за различных условий, включая следующие:

  • Получатель или частота входящих подключений слишком низка, чтобы соответствовать скорости поступающих данных.
  • Чрезмерная потеря данных возникает, возможно, из-за временных сетевых условий, таких как проблемы маршрутизации, нестабильность сети и т. д.
  • Неустранимая ошибка возникает у отправителя.
  • Чрезмерное использование ресурсов происходит на локальном компьютере, например превышение максимального допустимого внутреннего буферного хранилища или наличие состояния вне ресурсов.
  • Возникает ошибка проверки согласованности данных.
  • Сбой в компоненте PGM зависит от таких компонентов, как TCP/IP или Windows Sockets.

Как первый, так и второй элемент в приведенном выше списке могут привести к тому, что получатель выполняет чрезмерную буферизацию перед исчерпанием ресурсов или в конечном итоге оказывается за пределами окна отправителя.

Завершение сеанса PGM

Отправитель PGM или получатель может прекратить отправку или получение данных путем вызова closesocket. Получатель должен вызвать closesocket как на сокетах прослушивания, так и на принимающих сокетах, чтобы предотвратить утечку управляющих элементов. Вызов отключения на стороне отправителя перед вызовом closesocket обеспечивает отправку всех данных и сохраняет данные восстановления до тех пор, пока окно передачи не продвинется за последнюю последовательность данных, даже если приложение само завершит работу.