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

на главную

Жанры

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

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

Шрифт:

Connection.BytesLeft := Length(Connection.Msg);

// Ставим в очередь сообщение с событием FW_WRITE.

// Его получение заставит сервер отправить данные

PostMessage(Handle, WM_SOCKETMESSAGE, Msg.Socket, FD_WRITE);

end;

end

else if Res = 0 then

begin

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

' закрыл соединение');

RemoveConnection;

Exit;

end

elsе

//
Как обычно, "ошибку" WSAEWOULDBLOCK просто игнорируем

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

AddMessageToLog('Ошибка при получении данных от клиента ', +

Connection.ClientAddr + ': ' + GetErrorString);

RemoveConnection;

Exit;

end;

end

else if Connection.Phase = tpSendString then

// Если сервер находится на этапе отправки данных,

// а событие FD_READ все же произошло, отмечаем это

Connection.SendRead := True;

 end;

 FD_WRITE: begin

if Connection.Phase = tpSendString then

begin

// При наступлении события FD_WRITE проверяем, находится ли

// сервер на этапе отправки данных, и если да, отправляем их

Res :=

send(Connection.ClientSocket, Connection.Msg[Connection.Offset + 1],

Connection.BytesLeft, 0);

if Res > 0 then

begin

Inc(Connection.Offset, Res);

Dec(Connection.BytesLeft, Res);

// Если Connections. BytesLeft = 0, значит, строка отправлена

// полностью.

if Connection.BytesLeft = 0 then

begin

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

' отправлена строка: ' + Connection.Msg);

// Очищаем строку, просто чтобы сэкономить память

Connection.Msg := '';

// Следующий этап - снова получение длины строки от клиента

Connection.Phase := tpReceiveLength;

// Получено - 0 байт

Connection.Offset := 0;

// Осталось прочитать столько, сколько занимает целое число

Connection.BytesLeft := SizeOf(Integer);

// Если были промежуточные события FD_READ, вызываем их

// снова искусственно

it Connection.SendRead then

begin

PostMessage(Handle, WM_SOCKETMESSAGE, Msg.Socket, FD_READ);

Connection.SendRead := False;

end;

end;

end

else if WSAGetLastError <> WSAEWOULDBLOCK then

begin

AddMessageToLog('Ошибка
при отправке данных клиенту ' +

Connection.ClientAddr + ': ' + GetErrorString);

RemoveConnection;

Exit;

end;

end;

 end;

 FD_CLOSE: begin

// Клиент вызвал функцию shutdown. Закрываем соединение.

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

' закрыл соединение');

shutdown(Connection.ClientSocket, SD_BOTH);

RemoveConnection;

 end

 else

 begin

AddMessageToLog('Неверное событие при обмене с клиентом ' +

Connection.ClientAddr);

RemoveConnection;

 end;

 end;

end;

В этом примере можно найти много общего с кодом из листинга 2.32 — получение и отправка данных в зависимости от этапа выполняется практически одинаково, различаются только условия, при которых эти участки кода выполняются. Обратите внимание, что теперь проверка того, какой этап чтения выполняется, сделана взаимоисключающей, т.е. при обработке одного сообщения не может быть прочитана и длина строки, и сама строка. Это сделано, чтобы убрать ложные срабатывания. Рассмотрим два возможных варианта. Первый вариант — когда во входном буфере сокета оказывается сразу длина и строка (или ее часть). После того как будет прочитана длина, сообщение

WM_SOCKETMESSAGE
с параметром
FD_READ
вновь будет помещено в очередь, поскольку функция
recv
помещает это сообщение в очередь, если после ее вызова во входном буфере сокета остались данные. Если мы немедленно перейдем ко второму этапу, то прочитаем из буфера сокета все оставшиеся там данные, но сообщение в очереди все равно останется, что даст нам ложное срабатывание, когда петля сообщений извлечет и диспетчеризует это сообщение. Таким образом, выполнение сразу двух этапов при обработке одного сообщения не даст выигрыша в производительности, т.к. все равно придется извлекать и обрабатывать два сообщения.

Второй вариант — когда на момент обработки события

FD_READ
во входном буфере находится только длина строки. В этом случае функция
recv
не будет помещать в очередь второе сообщение
WM_SOCKETMESSAGE
, т.к. данных в буфере после ее выполнения не останется, но и попытка выполнить этап чтения строки окажется бесполезной работой, т.к. строка еще не получена. В любом случае этап чтения строки будет выполнен только при обработке следующего сообщения
WM_SOCKETMESSAGE
, когда от клиента будут получены новые данные.

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

Замуж второй раз, или Ещё посмотрим, кто из нас попал!

Вудворт Франциска
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Замуж второй раз, или Ещё посмотрим, кто из нас попал!

Протокол "Наследник"

Лисина Александра
1. Гибрид
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Протокол Наследник

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

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

Вперед в прошлое!

Ратманов Денис
1. Вперед в прошлое
Фантастика:
попаданцы
5.00
рейтинг книги
Вперед в прошлое!

Шесть принцев для мисс Недотроги

Суббота Светлана
3. Мисс Недотрога
Фантастика:
фэнтези
7.92
рейтинг книги
Шесть принцев для мисс Недотроги

Хочу тебя любить

Тодорова Елена
Любовные романы:
современные любовные романы
5.67
рейтинг книги
Хочу тебя любить

Огни Аль-Тура. Желанная

Макушева Магда
3. Эйнар
Любовные романы:
любовно-фантастические романы
эро литература
5.25
рейтинг книги
Огни Аль-Тура. Желанная

Начальник милиции 2

Дамиров Рафаэль
2. Начальник милиции
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Начальник милиции 2

Мастер...

Чащин Валерий
1. Мастер
Фантастика:
героическая фантастика
попаданцы
аниме
6.50
рейтинг книги
Мастер...

Сумеречный стрелок 8

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

Я до сих пор не князь. Книга XVI

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

Обыкновенные ведьмы средней полосы

Шах Ольга
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Обыкновенные ведьмы средней полосы

Метаморфозы Катрин

Ром Полина
Фантастика:
фэнтези
8.26
рейтинг книги
Метаморфозы Катрин

Идеальный мир для Социопата

Сапфир Олег
1. Социопат
Фантастика:
боевая фантастика
рпг
постапокалипсис
6.17
рейтинг книги
Идеальный мир для Социопата