Отправка и получение данных 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: 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.

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

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

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