. Эта процедура в бесконечном цикле устанавливает соединение, если оно не установлено, дает системе выполнить процедуру завершения, если это требуется, и выполняет какие-либо иные действия, не связанные с получением данных от сокета. Процедура завершения
GetData
получает и обрабатывает
данные, а если произошла ошибка, закрывает сокет и сбрасывает флаг
Connected
, что служит для процедуры
ProcessConnection
сигналом о необходимости установить соединение заново.
Из этого примера хорошо видны достоинства и недостатки процедур заверения. Получение и обработка данных выносится в отдельную процедуру, и с одной стороны, позволяет разгрузить основную процедуру, но, с другой стороны, заставляет прибегнуть к глобальным переменным для буфера и сокета.
Для протоколов, не поддерживающих соединение, существует другая функция для перекрытого получения данных —
WSARecvFrom
. Из названия очевидно, что она позволяет узнать адрес отправителя. Прототип функции
int WSASendTo(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount, LPDWORD lpNumberOfBytesSent, DWORD dwFlags, const struct sockaddr FAR *lpTo, int iToLen, LPWSAOVERLAPPED lpOverlapped, LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);
// *****
Описание на Delphi *****
function WSASend(S: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; var NumberOfBytesRecvd: DWORD; Flags: DWORD; lpOverlapped: PWSAOverlapped; lpCompletionRoutine: TWSAOverlappedCompletionRoutine): Integer;
function WSASendTo(S: TSocket; lpBuffers: PWSABuf; dwBufferCount: DWORD; var NumberOfBytesRecvd: DWORD; Flags: DWORD; var AddrTo: TSockAddr; ToLen: Integer; lpOverlapped: PWSAOverlapped; lpCompletionRoutine: TWSAOverlappedCompletionRoutine): Integer;
Если вы разобрались с функциями
WSARecv
,
send
и
sendto
, то смысл параметров функций
WSASend
и
WSASendTo
должен быть вам очевиден, поэтому подробно разбирать мы их не будем. Но отметим, что флаги передаются по значению, и функции не могут изменять их.
Потребность в перекрытом вводе-выводе при отправке данных возникает достаточно редко. Но функции
WSASend/WSASendTo
могут оказаться удобными при подготовке многокомпонентных пакетов, которые, например, имеют фиксированный заголовок и финальную часть. Для таких пакетов можно один раз подготовить буферы с заголовком и с финальной частью и, пользуясь возможностью отправки данных из несвязных буферов, при отправке каждого пакета менять только его среднюю часть.
В этом разделе мы рассмотрим создание сервера на основе перекрытого ввода-вывода на основе процедур завершения (пример кода с использованием событий есть в MSDN в описании функций
WSARecv
— и
WSASend
). Перекрытый ввод-вывод лучше подходит для обмена в режиме "запрос-ответ", поэтому мы вновь вернемся к первоначальному протоколу, который не предусматривает отправку сервером сообщений по собственному усмотрению. На компакт-диске этот пример называется OverlappedServеr.
Как обычно, для каждого соединения создается экземпляр записи
TConnection
, которая на этот раз выглядит так, как показано в листинге 2.76.
Листинг 2.76. Тип
TConnection
// Информация о соединении с клиентом:
// ClientSocket - сокет, созданный для взаимодействия с клиентом
// ClientAddr - строковое представление адреса клиента
// MsgSite - длина строки, получаемая от клиента
// Msg - строка, получаемая от клиента или отправляемая ему
// Offset - количество байтов, уже полученных от клиента
// или отправляемых ему на данном этапе
// BytesLeft - сколько байтов осталось получить от клиента
// или отправить ему на данном этапе
// Overlapped - структура для выполнения перекрытой операции