Чтение онлайн

на главную

Жанры

О чём не пишут в книгах по Delphi

Григорьев Антон Борисович

Шрифт:

Параметр

lpOverlapped
функции
AcceptEx
не может быть равным -1, а его поле
hEvent
должно указывать на корректное событие. Процедуры завершения не предусмотрены. Если на момент вызова функции клиент уже подключился и прислал первую порцию данных (или место для данных в буфере не зарезервировано),
AcceptEx
возвращает
True
. Если же клиент еще не подключился, или подключился, но не прислал данные, функция
AcceptEx
возвращает
False
, а
WSAGetLastError
ERROR_IO_PENDING
. Параметр
lpBytesReceived
в этом случае остается без изменений.

Проконтролировать состояние операции можно с помощью функции

GetOverlappedResult
, которая является аналогом известной нам функции
WSAGetOverlappedResult
, за исключением того, что использует запись
TOverlapped
вместо
TWSAOverlapped
и не предусматривает передачу флагов. С ее помощью можно узнать, завершилась ли операция, а также дождаться ее завершения и узнать, сколько байтов прислано клиентом (функция
AcceptEx
не ждет, пока клиент заполнит весь буфер, предназначенный для него — для завершения операции подключения достаточно первого пакета).

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

getsockopt
для сокета
sAcceptSocket
узнавать значение целочисленного параметра
SO_CONNECT_TIME
уровня
SOL_SOCKET
. Этот параметр показывает время в секундах, прошедшее с момента подключения клиента к данному сокету (или -1, если подключения не было). Если подключившийся клиент слишком долго не присылает данных, сокет
sAcceptSocket
следует закрыть, что приведет к завершению операции, начатой
AcceptEx
, с ошибкой. После этого можно снова вызывать
AcceptEx
для приема новых клиентов.

Функция

AcceptEx
реализована таким образом, чтобы обеспечивать максимальную скорость подключения. Ранее мы говорили, что сокеты, созданные функциями
accept
и
WSAAccept
, наследуют параметры слушающего сокета (например, свойства асинхронного режима). Для повышения производительности сокет
sAcceptSocket
по умолчанию не получает свойств сокета
sListenSocket
. Но он может унаследовать их после завершения операции с помощью следующей установки параметра сокета
SO_UPDATE_ACCEPT_CONTEXT
:

setsockopt(sAcceptSocket, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT, PChar(@sListenSocket), SizeOf(sListenSocket));

Ha сокет

sAcceptedSocket
после его подключения к клиенту накладываются ограничения: он может использоваться не во всех функциях WinSock, а только в следующих:
send
,
WSASend
,
recv
,
WSARecv
,
ReadFile
,
WriteFile
,
TransmitFile
,
closesocket
и
setsockopt
, причем в последней — только для установки параметра
SO_UPDATE_ACCEPT_CONTEXT
.

В WinSock не документируется, в какую именно часть буфера помещаются адрес клиента и принявшего его сокета. Вместо этого предоставляется функция

GetAcceptExSockAddrs
, прототип которой приведен в листинге 2.83.

Листинг 2.83. Функция
GetAcceptExSockAddrs

procedure GetAcceptExSockAddrs(lpOutputBuffer: Pointer; dwReceiveDataLength: DWORD; dwLocalAddressLength: DWORD; dwRemoteAddressLength: DWORD; var LocalSockaddr: PSockAddr; var LocalSockaddrLength: Integer; var RemoteSockaddr: PSockAddr; var RemoteSockaddrLength: Integer);

Примечание

В 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.

Листинг 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
лучше установить равным нулю.

Поделиться:
Популярные книги

Идущий в тени 4

Амврелий Марк
4. Идущий в тени
Фантастика:
боевая фантастика
6.58
рейтинг книги
Идущий в тени 4

Дракон с подарком

Суббота Светлана
3. Королевская академия Драко
Любовные романы:
любовно-фантастические романы
6.62
рейтинг книги
Дракон с подарком

Я снова не князь! Книга XVII

Дрейк Сириус
17. Дорогой барон!
Фантастика:
юмористическое фэнтези
попаданцы
аниме
5.00
рейтинг книги
Я снова не князь! Книга XVII

Метка драконов. Княжеский отбор

Максименко Анастасия
Фантастика:
фэнтези
5.50
рейтинг книги
Метка драконов. Княжеский отбор

Авиатор: назад в СССР 11

Дорин Михаил
11. Покоряя небо
Фантастика:
альтернативная история
5.00
рейтинг книги
Авиатор: назад в СССР 11

На границе империй. Том 7. Часть 5

INDIGO
11. Фортуна дама переменчивая
Фантастика:
боевая фантастика
космическая фантастика
попаданцы
5.00
рейтинг книги
На границе империй. Том 7. Часть 5

Темный охотник 6

Розальев Андрей
6. КО: Темный охотник
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Темный охотник 6

Корпулентные достоинства, или Знатный переполох. Дилогия

Цвик Катерина Александровна
Фантастика:
юмористическая фантастика
7.53
рейтинг книги
Корпулентные достоинства, или Знатный переполох. Дилогия

Все еще не Герой!. Том 2

Довыдовский Кирилл Сергеевич
2. Путешествие Героя
Фантастика:
боевая фантастика
юмористическое фэнтези
городское фэнтези
рпг
5.00
рейтинг книги
Все еще не Герой!. Том 2

Довлатов. Сонный лекарь 3

Голд Джон
3. Не вывожу
Фантастика:
попаданцы
аниме
5.00
рейтинг книги
Довлатов. Сонный лекарь 3

Попаданка в деле, или Ваш любимый доктор - 2

Марей Соня
2. Попаданка в деле, или Ваш любимый доктор
Любовные романы:
любовно-фантастические романы
7.43
рейтинг книги
Попаданка в деле, или Ваш любимый доктор - 2

Возмездие

Злобин Михаил
4. О чем молчат могилы
Фантастика:
фэнтези
7.47
рейтинг книги
Возмездие

Ваше Сиятельство 8

Моури Эрли
8. Ваше Сиятельство
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Ваше Сиятельство 8

Чемпион

Демиров Леонид
3. Мания крафта
Фантастика:
фэнтези
рпг
5.38
рейтинг книги
Чемпион