Функция TransmitFile
кладет данные из файла в буфер сокета по частям. Параметр nNumberOfBytesPerSend
определяет размер одной порции данных. Он может быть равен нулю — в этом случае система сама определяет размер порции. Этот параметр критичен только в случае дейтаграммных протоколов, потому что при этом размер порции определяет размер дейтаграммы. Для TCP данные, хранящиеся в буфере, передаются в сеть целиком или по частям в зависимости от загрузки сети, готовности принимающей стороны и т.п., а какими порциями они попали в буфер, на размер пакета почти не влияет. Поэтому для TCP-сокета параметр nNumberOfBytesPerSend
лучше установить равным нулю.
Параметр lpOverlapped
указывает на запись TOverlapped
, использующуюся для перекрытого ввода-вывода. Эту структуру мы обсуждали при описании функции AcceptEx
. В отличие от AcceptEx
, в TransmitFile
этот параметр добыть равным nil
, и тогда операция передачи файла не будет перекрытой.
Если параметр lpOverlapped
равен nil
, передача файла начинается с той позиции, на которую указывает файловый указатель (для только что открытого файла этот указатель указывает на его начало, а переместить его можно, например, с помощью функции SetFilePointer
; также он перемещается при чтении файла с помощью ReadFile
). Если же параметр lpOverlapped
задан, то передача файла начинается с позиции, заданной значениями полей Offset
и OffsetHigh
, которые должны содержать соответственно младшую и старшую часть 64-битного смещения стартовой позиции от начала файла.
Параметр lpTransmitBuffers
является указателем на запись TTransmitFileBuffers
, объявленную так, как показано в листинге 2.85.
Листинг 2.85. Тип TTransmitFileBuffers
PTransmitFileBuffers = ^TTransmitFileBuffers;
_TRANSMIT_FILE_BUFFERS = record
Head: Pointer;
HeadLength: DWORD;
Tail: Pointer;
TailLength: DWORD;
end;
TTransmitFileBuffers = _TRANSMIT_FILE_BUFFERS;
С ее помощью можно указывать буферы, содержащие данные, которые должны быть отправлены перед передачей самого файла и после него. Поле Head
содержит указатель на буфер, содержащий данные, предназначенные для отправки перед файлом, HeadLength
— размер этих данных. Аналогично Tail
и TailLength
определяют начало и длину буфера с данными, которые передаются после передачи файла. Если передача дополнительных данных не нужна, параметр lpTransmitBuffer
может быть равен nil
.
Допускается и обратная ситуация: параметр hFile
может быть равен нулю, тогда передаются только данные, определяемые параметром lpTransmitBuffer
.
Последний параметр функции TransmitFile
в модуле WinSock
имеет имя Reserved
. В WinSock 1 он и в самом деле был зарезервирован и не имел смысла, но в WinSock 2 через него передаются флаги, управляющие операцией передачи файла. Мы не будем приводить здесь полный список возможных флагов (он есть в MSDN), а ограничимся лишь самыми важными. Указание флага TF_USE_DEFAULT_WORKER
или TF_USE_SYSTEM_THREAD
позволяет повысить производительность при передаче больших файлов, a TF_USE_KERNEL_APC
— при передаче маленьких файлов. Вообще, при работе с функцией TransmitFile
чтение файла и передачу данных в сеть осуществляет ядро операционной системы, что приводит к повышению быстродействия по сравнению с использованием ReadFile
и send
самой программой.
Функция TransmitFile
реализована по-разному в серверных версиях Windows NT/2000 и в остальных системах: в серверных версиях она оптимизирована по быстродействию, а в остальных — по количеству необходимых ресурсов.
Данные, переданные функцией TransmitFile
, удаленная сторона должна принимать обычным образом, с помощью функций recv/WSARecv
.
На этом мы заканчиваем рассмотрение WinSock. Многие возможности этого стандарта остались не рассмотренными и даже не упомянутыми. Но для этого существуют книги, подобные [3]. Нашей же основной задачей было последовательное знакомство с базовыми возможностями WinSock API и способам их применения в Delphi.
Следует отметить, что в Delphi не обязательно напрямую использовать WinSock API, чтобы работать с сокетами, т.к. VCL содержит компоненты для этого. Прежде всего это TServerSocket
и TClientSocket
, использующие асинхронные сокеты, основанные на оконных сообщениях. Начиная с Delphi 7, к ним добавились компоненты TTCPServer
, TTCPClient
и TUDPSocket
, использующие блокирующие или неблокирующие сокеты. Кроме того, с Delphi поставляется библиотека Indy, которая тоже содержит компоненты для работы с сокетами. Но практика показывает, что освоить эти компоненты без знания особенностей WinSock API очень сложно, так что даже если вы никогда не будете вызывать функции WinSock API явно, а ограничитесь компонентами. информация, изложенная в этой главе, вам все равно пригодится.
Читать дальше
Конец ознакомительного отрывка
Купить книгу