В Delphi до 7-й версии включительно модуль WinSock содержит ошибку — параметры LocalSockaddr
и RemoteSockaddr
функции GetAcceptExSockAddrs
имеют в нем тип TSockAddr
вместо PSockAddr
. Из-за этой ошибки функцию GetAcceptExSockAddrs
в этих версиях Delphi необходимо самостоятельно импортировать. Следует заметить, что во многих модулях для WinSock 2 от независимых разработчиков объявление этой функции скопировано из стандартного модуля вместе с ошибкой.
Первые четыре параметра функции GetAcceptExSockAddrs
определяют буфер, в котором в результате вызова AcceptEx
оказались данные от клиента и адреса, и размеры частей буфера, зарезервированных для данных и для адресов. Значения этих параметров должны совпадать со значениями аналогичных параметров в соответствующем вызове AcceptEx
. Через параметр LocalSockaddrs
возвращается указатель на то место в буфере, в котором хранится адрес привязки сокета sAcceptSocket
, а через параметр LocalSockaddrsLength
— длина адреса (16 в случае TCP). Адрес клиента и его длина возвращаются через параметры RemoteSockaddrs
и RemoteSockaddrsLength
. Следует особенно подчеркнуть, что указатели LocalSockaddrs
и RemoteSockaddrs
указывают именно на соответствующие части буфера: память для них специально не выделяется и, следовательно, не должна освобождаться, а свою актуальность они теряют при освобождении буфера.
Последняя из дополнительных функций, TransmitFile
, служит для передачи файлов по сети. Ее прототип приведен в листинге 2.84.
TransmitFile
function TransmitFile(hSocket: TSocket; hFile: THandle; nNumberOfBytesToWrite, nNumberOfBytesPerSend: DWORD; lpOverlapped: POverlapped; lpTransmitBuffers: PTransmitFileBuffers; dwReserved: DWORD): BOOL;
Функция TransmitFile
отправляет содержимое указанного файла через указанный сокет. При этом допускаются только протоколы, поддерживающие соединение, т. е. использовать данную функцию с UDP-сокетом нельзя. Сокет задается параметром hSocket
, файл — параметром hFile
. Дескриптор файла обычно получается с помощью функции стандартного API CreateFile
. Файл рекомендуется открывать с флагом FILE_FLAG_SEQUENTIAL_SCAN
, т. к. это повышает производительность.
Параметр nNumberOfBytesToWrite
определяет, сколько байтов должно быть передано (позволяя, тем самым, передавать не весь файл, а только его часть). Если этот параметр равен нулю, передается весь файл.
Функция TransmitFile
кладет данные из файла в буфер сокета по частям. Параметр nNumberOfBytesPerSend
определяет размер одной порции данных. Он может быть равен нулю — в этом случае система сама определяет размер порции. Этот параметр критичен только в случае дейтаграммных протоколов, потому что при этом размер порции определяет размер дейтаграммы. Для TCP данные, хранящиеся в буфере, передаются в сеть целиком или по частям в зависимости от загрузки сети, готовности принимающей стороны и т. п., а какими порциями они попали в буфер, на размер пакета почти не влияет. Поэтому для TCP-сокета параметр nNumberOfBytesPerSend
лучше установить равным нулю.
Параметр lpOverlapped
указывает на запись TOverlapped
, использующуюся для перекрытого ввода-вывода. Эту структуру мы обсуждали при описании функции AcceptEx
. В отличие от AcceptEx
, в TransmitFile
этот параметр добыть равным nil
, и тогда операция передачи файла не будет перекрытой.
Если параметр lpOverlapped
равен nil
, передача файла начинается с той позиции, на которую указывает файловый указатель (для только что открытого файла этот указатель указывает на его начало, а переместить его можно, например, с помощью функции SetFilePointer
; также он перемещается при чтении файла с помощью ReadFile
). Если же параметр lpOverlapped
задан, то передача файла начинается с позиции, заданной значениями полей Offset
и OffsetHigh
, которые должны содержать соответственно младшую и старшую часть 64-битного смещения стартовой позиции от начала файла.