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

на главную

Жанры

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

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

Шрифт:

'" не является целым числом', mtError, [mbOK], 0);

on ERangeError do

// Это исключение может возникнуть только в одном месте -

// при присваивании значения номеру порта

MessageDlg('Номер порта должен находиться в диапазоне 1-65535',

mtError, [mbOK], 0);

 end;

end;

Так как протокол TCP допускает разбиение посылки на произвольное число пакетов, возможна ситуация,

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

Взаимодействие сервера с клиентом состоит из трех этапов. На первом этапе сервер получает от клиента четырёхбайтное значение — длину строки. На втором этапе сервер получает от клиента саму строку, размер которой уже известен из величины, полученной на первом этапе. На третьем этапе сервер отправляет ответ клиенту, состоящий из строки, завершающейся нулем. Чтобы при очередном "тике" таймера сервер мог продолжить общение с клиентом, прерванное в произвольном месте, необходимо запоминать, на каком этапе было прервано взаимодействие в предыдущий раз, сколько байтов на данном этапе уже прочитано или отправлено и сколько еще осталось прочитать или отправить. Для хранения этих данных мы будем использовать типы

TTransportPhase
и
TConnection
(листинг 2.31).

Листинг 2.31. Типы
TTransportPhase
и
TConnection
 

type

 // Этап взаимодействия с клиентом:

 // tpReceiveLength - сервер ожидает от клиента длину строки

 // tpReceiveString - сервер ожидает от клиента строку

 // tpSendString - сервер посылает клиенту строку

 TTransportPhase = (tpReceiveLength, tpReceiveString, tpSendString);

 // Информация о соединении с клиентом:

 // СlientSocket - сокет, созданный для взаимодействия с клиентом

 // ClientAddr - строковое представление адреса клиента

 // MsgSize - длина строки, получаемая от клиента

 // Msg - строка, получаемая от клиента или отправляемая ему,

 // Phase - этап взаимодействия с данным клиентом

 // Offset - количество байтов, уже полученных от клиента

 // или отправленных ему на данном этапе

 // BytesLeft - сколько байтов осталось получить от клиента

 // или отправить ему на данном этапе

 PConnection = ^TConnection;

 TConnection = record

ClientSocket: TSocket;

ClientAddr: string;

MsgSize: Integer;

Msg: string;

Phase: TTransportPhase;

Offset: Integer;

BytesLeft: Integer;

 end;

Для

каждого подключившегося клиента создается отдельный экземпляр записи
TConnection
, в котором хранится информация как о самом подключении, так и о том, на каком этапе находится взаимодействие с данным клиентом.

Проверка подключения клиентов и взаимодействие с подключившимися ранее реализуется, как уже было сказано, при обработке события таймера. Код обработчика приведен в листинге 2.32. 

Листинг 2.32. Обработчик события таймера

// Обработка сообщения от таймера

// В ходе обработки проверяется наличие вновь подключившихся клиентов

// а также осуществляется обмен данными с клиентами

procedure TServerForm.TimerReadTimer(Sender: TObject);

var

 // Сокет, который создается для вновь подключившегося клиента

 ClientSocket: TSocket;

 // Адрес подключившегося клиента

 ClientAddr: TSockAddr;

 // Длина адреса

 AddrLen: Integer;

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

 NewConnection: PConnection;

 I: Integer;

begin

 AddrLen := SizeOf(TSockAddr);

 // Проверяем наличие подключении. Так как сокет неблокирующий,

 // accept не будет блокировать нить даже в случае отсутствия

 // подключений.

 ClientSocket := accept(FServerSocket, @ClientAddr, @AddrLen);

 if ClientSocket = INVALID_SOCKET then

 begin

// Если произошедшая ошибка - WSAEWOULDBLOCK, это просто означает,

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

// поэтому ошибку WSAEWOULDBLOCK мы просто игнорируем. Прочие же

// ошибки могут произойти только в случае серьезных проблем,

// которые требуют остановки сервера.

if WSAGetLastError <> WSAEWOULDBLOCK then

begin

MessageDlg('Ошибка при подключении клиента:'#13#10 +

GetErrorString + #13#10'Сервер будет остановлен', mtError, [mbOK], 0);

ClearConnections;

closesocket(FServerSocket);

OnStopServer;

end;

 end

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

Пропала, или Как влюбить в себя жену

Юнина Наталья
2. Исцели меня
Любовные романы:
современные любовные романы
6.70
рейтинг книги
Пропала, или Как влюбить в себя жену

Адепт: Обучение. Каникулы [СИ]

Бубела Олег Николаевич
6. Совсем не герой
Фантастика:
фэнтези
попаданцы
9.15
рейтинг книги
Адепт: Обучение. Каникулы [СИ]

Калибр Личности 1

Голд Джон
1. Калибр Личности
Фантастика:
попаданцы
альтернативная история
аниме
5.00
рейтинг книги
Калибр Личности 1

У врага за пазухой

Коваленко Марья Сергеевна
5. Оголенные чувства
Любовные романы:
остросюжетные любовные романы
эро литература
5.00
рейтинг книги
У врага за пазухой

Бракованная невеста. Академия драконов

Милославская Анастасия
Фантастика:
фэнтези
сказочная фантастика
5.00
рейтинг книги
Бракованная невеста. Академия драконов

Возвышение Меркурия. Книга 2

Кронос Александр
2. Меркурий
Фантастика:
фэнтези
5.00
рейтинг книги
Возвышение Меркурия. Книга 2

Наследник павшего дома. Том II

Вайс Александр
2. Расколотый мир [Вайс]
Фантастика:
фэнтези
попаданцы
аниме
5.00
рейтинг книги
Наследник павшего дома. Том II

Попаданка в академии драконов 2

Свадьбина Любовь
2. Попаданка в академии драконов
Любовные романы:
любовно-фантастические романы
6.95
рейтинг книги
Попаданка в академии драконов 2

Теневой путь. Шаг в тень

Мазуров Дмитрий
1. Теневой путь
Фантастика:
фэнтези
6.71
рейтинг книги
Теневой путь. Шаг в тень

Архил...? Книга 2

Кожевников Павел
2. Архил...?
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Архил...? Книга 2

Искатель. Второй пояс

Игнатов Михаил Павлович
7. Путь
Фантастика:
фэнтези
боевая фантастика
6.11
рейтинг книги
Искатель. Второй пояс

Решала

Иванов Дмитрий
10. Девяностые
Фантастика:
попаданцы
альтернативная история
5.00
рейтинг книги
Решала

70 Рублей - 2. Здравствуй S-T-I-K-S

Кожевников Павел
Вселенная S-T-I-K-S
Фантастика:
боевая фантастика
постапокалипсис
5.00
рейтинг книги
70 Рублей - 2. Здравствуй S-T-I-K-S

Не верь мне

Рам Янка
7. Самбисты
Любовные романы:
современные любовные романы
5.00
рейтинг книги
Не верь мне