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

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

Жанры

О чём не пишут в книгах по 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));

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

Измена. Испорченная свадьба

Данич Дина
Любовные романы:
современные любовные романы
короткие любовные романы
5.00
рейтинг книги
Измена. Испорченная свадьба

Последний из рода Демидовых

Ветров Борис
Фантастика:
детективная фантастика
попаданцы
аниме
5.00
рейтинг книги
Последний из рода Демидовых

Его наследник

Безрукова Елена
1. Наследники Сильных
Любовные романы:
современные любовные романы
эро литература
5.87
рейтинг книги
Его наследник

Измена. Право на семью

Арская Арина
Любовные романы:
современные любовные романы
5.20
рейтинг книги
Измена. Право на семью

Неудержимый. Книга XIX

Боярский Андрей
19. Неудержимый
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Неудержимый. Книга XIX

Волков. Гимназия №6

Пылаев Валерий
1. Волков
Фантастика:
попаданцы
альтернативная история
аниме
7.00
рейтинг книги
Волков. Гимназия №6

Неучтенный. Дилогия

Муравьёв Константин Николаевич
Неучтенный
Фантастика:
боевая фантастика
попаданцы
7.98
рейтинг книги
Неучтенный. Дилогия

Безумный Макс. Ротмистр Империи

Ланцов Михаил Алексеевич
2. Безумный Макс
Фантастика:
героическая фантастика
альтернативная история
4.67
рейтинг книги
Безумный Макс. Ротмистр Империи

Проданная Истинная. Месть по-драконьи

Белова Екатерина
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Проданная Истинная. Месть по-драконьи

Род Корневых будет жить!

Кун Антон
1. Тайны рода
Фантастика:
фэнтези
попаданцы
аниме
7.00
рейтинг книги
Род Корневых будет жить!

Брак по-драконьи

Ардова Алиса
Фантастика:
фэнтези
8.60
рейтинг книги
Брак по-драконьи

Боги, пиво и дурак. Том 3

Горина Юлия Николаевна
3. Боги, пиво и дурак
Фантастика:
фэнтези
попаданцы
5.00
рейтинг книги
Боги, пиво и дурак. Том 3

Отморозок 3

Поповский Андрей Владимирович
3. Отморозок
Фантастика:
попаданцы
5.00
рейтинг книги
Отморозок 3

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

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