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

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

Жанры

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

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

Шрифт:

 else

 begin

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

New(NewConnection);

NewConnection.ClientSocket := ClientSocket;

NewConnection.СlientAddr :=

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.Phase := tpReceiveLength;

NewConnection.Offset := 0;

NewConnection.BytesLeft := SizeOf(Integer);

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

FConnections.Add(NewConnection);

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

NewConnection.ClientAddr);

 end;

 // Обрабатываем все существующие подключения.

 // Цикл идет от конца списка к началу потому, что в ходе

 // обработки соединение может быть удалено из списка.

 for I := FConnections.Count - 1 downto 0 do processConnection(I);

end;

Обратите внимание, что сокет, созданный функцией

accept
, нигде не переводится в неблокирующий режим. Это связано с тем, что такой сокет наследует свойства слушающего сокета, поэтому он в данном случае сразу создается неблокирующим.

Собственно взаимодействие сервера с клиентом вынесено в метод

ProcessConnection
(листинг 2.33). который осуществляет чтение данных от клиента и отправку данных в соответствии с этапом, на котором остановилось взаимодействие. При реализации этого метода необходимо просто аккуратно следить за тем, куда и сколько данных нужно передать.

Листинг 2.33. Метод
ProcessConnection

// Обработка клиента. Index задает индекс записи в списке

procedure TServerForm.ProcessConnection(Index: Integer);

var

 // Вспомогательная переменная, чтобы не приводить каждый раз

 // FConnections[Index] к PConnection

 Connection: PConnection;

 // Результат вызова recv и send

 Res: Integer;

 // Вспомогательная процедура, освобождающая ресурсы, связанные

 // с клиентом и удаляющая запись подключения из списка

 procedure RemoveConnection;

 begin

closesocket(Connection.ClientSocket);

Dispose(Connection);

FConnections.Delete(Index);

 end;

begin

 Connection := PConnection(PConnections[Index]);

 //
Проверяем, на каком этапе находится взаимодействие с клиентом.

 // Используется оператор if, а не case, потому, что в случае case

 // выполняется только одна альтернатива, а в нашем случае в ходе

 // выполнения этапа он может завершиться, и взаимодействие

 // перейдет к следующему этапу. Использование if позволяет выполнить

 // все три этапа, если это возможно, а не один из них.

 if Connection.Phase = tpReceiveLength then

 begin

// Этап получения от клиента длины строки. При выполнении этого

// этапа сервер получает от клиента длину строки и размещает ее

// в поле Connection.MsgSize. Здесь приходится учитывать, что

// теоретически даже такая маленькая (4 байта) посылка может

// быть разбита на несколько пакетов, поэтому за один раз этот

// этап не будет завершен, и второй раз его придется продолжать,

// загружая оставшиеся байты. Connection.Offset — количество

// уже прочитанных на данном этапе байтов - одновременно является

// смещением, начиная с которого заполняется буфер.

Res := recv(Connection.ClientSocket, (PChar(@Connection.MsgSize) +

Connection.Offset)^, Connection.BytesLeft, 0);

if Res > 0 then

begin

// Если Res > 0, это означает, что получено Res байтов.

// Соответственно, увеличиваем на Res количество прочитанных

// на данном этапе байтов и на такую же величину уменьшаем

// количество оставшихся.

Inc(Connection.Offset, Res);

Dec(Connection.BytesLeft, Res);

// Если количество оставшихся байтов равно нулю, можно переходить

// к следующему этапу.

if Connection.BytesLeft = 0 then

begin

// Проверяем корректность принятой длины строки

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

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

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

Бывшие. Война в академии магии

Берг Александра
2. Измены
Любовные романы:
любовно-фантастические романы
7.00
рейтинг книги
Бывшие. Война в академии магии

Мастер клинков. Начало пути

Распопов Дмитрий Викторович
1. Мастер клинков
Фантастика:
фэнтези
9.16
рейтинг книги
Мастер клинков. Начало пути

Имя нам Легион. Том 8

Дорничев Дмитрий
8. Меж двух миров
Фантастика:
боевая фантастика
рпг
аниме
5.00
рейтинг книги
Имя нам Легион. Том 8

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

Вирго Софи
1. Чем закончится измена
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Измена. Право на счастье

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

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

Камень. Книга 4

Минин Станислав
4. Камень
Фантастика:
боевая фантастика
7.77
рейтинг книги
Камень. Книга 4

Измена. Мой заклятый дракон

Марлин Юлия
Любовные романы:
любовно-фантастические романы
7.50
рейтинг книги
Измена. Мой заклятый дракон

Предатель. Цена ошибки

Кучер Ая
Измена
Любовные романы:
современные любовные романы
5.75
рейтинг книги
Предатель. Цена ошибки

Звездная Кровь. Изгой

Елисеев Алексей Станиславович
1. Звездная Кровь. Изгой
Фантастика:
боевая фантастика
попаданцы
рпг
5.00
рейтинг книги
Звездная Кровь. Изгой

Рождение победителя

Каменистый Артем
3. Девятый
Фантастика:
фэнтези
альтернативная история
9.07
рейтинг книги
Рождение победителя

Барону наплевать на правила

Ренгач Евгений
7. Закон сильного
Фантастика:
боевая фантастика
попаданцы
аниме
5.00
рейтинг книги
Барону наплевать на правила

Камень. Книга шестая

Минин Станислав
6. Камень
Фантастика:
боевая фантастика
7.64
рейтинг книги
Камень. Книга шестая

Чужая дочь

Зика Натаэль
Любовные романы:
любовно-фантастические романы
5.00
рейтинг книги
Чужая дочь