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

на главную - закладки

Жанры

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

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

Шрифт:

mtError, [mbOK], 0);

closesocket(ClientSocket);

Exit;

end;

Arg := 0;

if ioctlsocket(ClientSocket, FIONBIO, Arg) = SOCKET_ERROR then

begin

MessageDlg('Ошибка при переводе подключившегося сокета ' +

'в блокирующий режим:'#13#10 + GetErrorString,

mtError, [mbOK], 0);

closesocket(ClientSocket);

Exit;

end;

//
Создаем запись для нового подключения и заполняем ее

New(NewConnection);

NewConnection.ClientSocket := ClientSocket;

NewConnection.ClientAddr :=

Format('%u.%u.%u.%u:%u, [

Ord(ClientAddr.sin_addr.S_un_b.s_b1),

Ord(ClientAddr.sin_addr.S_un_b.s_b2),

Ord(ClientAddr.sin_addr.S_un_b.s_b3),

Ord(ClientAddr.sin_addr.S_un_b.s_b4),

ntohs(ClientAddr.sin_port)]);

NewConnection.Offset := 0;

NewConnection.BytesLeft := SizeOf(Integer);

NewConnection.Overlapped.hEvent := 0;

// Добавляем запись нового соединения в список

FConnections.Add(NewConnection);

AddMessageToLog('Зафиксировано подключение с адреса ' +

NewConnection.ClientAddr);

// Начинаем перекрытый обмен с сокетом.

// Начинаем, естественно, с чтения длины строки,

// в качестве принимающего буфера используем NewConnection.MsgSize

Buf.Len := NewConnection.BytesLeft;

Buf.Buf := @NewConnection.MsgSize;

Flags := 0;

if WSARecv(NewConnection.ClientSocket, @Buf, 1, NumBytes, Flags,

@NewConnection.Overlapped, ReadLenCompleted) = SOCKET_ERROR then

begin

if WSAGetLastError <> WSA_IO_PENDING then

begin

AddMessageToLog('Клиент ' + NewConnection.ClientAddr +

' - ошибка при чтении длины строки: ' + GetErrorString);

RemoveConnection(NewConnection);

end;

end;

 end;

end;

После того как сокет для взаимодействия с подключившимся клиентом создан, следует отменить для него асинхронный режим, унаследованный от слушающего сокета, т.к. при перекрытом вводе-выводе этот режим не нужен. Затем, после создания экземпляра

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

Как мы уже говорили ранее, в программе

OverlappedServer
есть три разных функции завершения:
ReadLenCompleted
,
ReadMsgCompleted
и
SendMsgCompleted
. Последовательность работы с ними такая: сначала для чтения длины строки вызывается
WSARecv
, в качестве
буфера передастся
Connection.MsgSize
, в качестве функции завершения —
ReadLenCompleted
(это мы уже видели в листинге 2.77). Когда вызывается
ReadLenCompleted
, это значит, что операция чтения уже завершена и прочитанная длина находится в
Connection.MsgSize
. Поэтому в функции
ReadLenCompleted
выделяем нужный размер для строки
Connection.Msg
и запускаем следующую операцию перекрытого чтения — с буфером
Connection.Msg
и функцией завершения
ReadMsgCompleted
. В этой функции полученная строка показывается пользователю, формируется ответ, и запускается следующая операция перекрытого ввода-вывода — отправка строки клиенту. В качестве буфера в функцию
WSASend
передаётся
Connection.Msg
, а в качестве функции завершения —
SendMsgCompleted
. В функции
SendMsgCompleted
вновь вызывается
WSARecv
с буфером
Connection.MsgSize
и функцией завершения
ReadLenCompleted
, и таким образом сервер возвращается к первому этапу взаимодействия с клиентом.

Описанную простую последовательность действий портит то, что из-за возможной отправки данных по частям можно столкнуться с ситуацией, когда функция завершения вызвана для уведомления о том, что получена или отправлена часть данных. Чтобы получить остальную их часть, необходимо вновь вызвать функцию чтения или записи с той же функцией завершения, а указатель на буфер должен при этом указывать на оставшуюся незаполненной часть переменной, в которую помещаются данные. С учетом этого, а также необходимости обработки ошибок, функции завершения выглядят так, как показано в листинге 2.78.

Листинг 2.78. Функции завершения

// Функция ReadLenCompleted используется в качестве функции завершения

// для перекрытого чтения длины строки

procedure ReadLenCompleted(dwError: DWORD; cdTransferred: DWORD; lpOverlapped: PWSAOverlapped; dwFlags: DWORD); stdcall;

var

 // Указатель на соединение

 Connection: PConnection;

 // Указатель на буфер

 Buf: TWSABuf;

 // Параметры для WSARecv

 NumBytes, Flags: DWORD;

begin

 // Для идентификации операции в функцию передается указатель

 // на запись TWSAOverlapped. Ищем по этому указателю

 // подходящее соединение в списке FConnections.

 Connection := ServerForm.GetConnectionByOverlapped(lpOverlapped);

 if Connection = nil then

 begin

ServerForm.AddMessageToLog(

'Внутренняя ошибка программы - не найдено соединение');

Exit;

 end;

 // Проверяем, что не было ошибки

 if dwError <> 0 then

 begin

ServerForm.AddMessageToLog('Клиент ' + Connection.ClientAddr +

' - ошибка при чтении длины строки: ' + GetErrorString(dwError));

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

70 Рублей

Кожевников Павел
1. 70 Рублей
Фантастика:
фэнтези
боевая фантастика
попаданцы
постапокалипсис
6.00
рейтинг книги
70 Рублей

Жатва душ. Остров мертвых

Сугралинов Данияр
Фантастика:
боевая фантастика
рпг
5.20
рейтинг книги
Жатва душ. Остров мертвых

Сердце Дракона. Том 9

Клеванский Кирилл Сергеевич
9. Сердце дракона
Фантастика:
фэнтези
героическая фантастика
боевая фантастика
7.69
рейтинг книги
Сердце Дракона. Том 9

Как я строил магическую империю 6

Зубов Константин
6. Как я строил магическую империю
Фантастика:
попаданцы
аниме
фантастика: прочее
фэнтези
5.00
рейтинг книги
Как я строил магическую империю 6

Леди для короля. Оборотная сторона короны

Воронцова Александра
3. Королевская охота
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Леди для короля. Оборотная сторона короны

Кодекс Крови. Книга VI

Борзых М.
6. РОС: Кодекс Крови
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Кодекс Крови. Книга VI

Газлайтер. Том 4

Володин Григорий
4. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 4

АллатРа

Новых Анастасия
Научно-образовательная:
психология
история
философия
обществознание
физика
6.25
рейтинг книги
АллатРа

Газлайтер. Том 10

Володин Григорий
10. История Телепата
Фантастика:
боевая фантастика
5.00
рейтинг книги
Газлайтер. Том 10

Дорога к счастью

Меллер Юлия Викторовна
Любовные романы:
любовно-фантастические романы
6.11
рейтинг книги
Дорога к счастью

Газлайтер. Том 8

Володин Григорий
8. История Телепата
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Газлайтер. Том 8

Камень Книга седьмая

Минин Станислав
7. Камень
Фантастика:
фэнтези
боевая фантастика
6.22
рейтинг книги
Камень Книга седьмая

Николай I Освободитель. Книга 2

Савинков Андрей Николаевич
2. Николай I
Фантастика:
героическая фантастика
альтернативная история
5.00
рейтинг книги
Николай I Освободитель. Книга 2

Секретарша генерального

Зайцева Мария
Любовные романы:
современные любовные романы
эро литература
короткие любовные романы
8.46
рейтинг книги
Секретарша генерального