Листинг 11.9.
Процедуры обработки событий серверного приложения (Unitl.pas)
procedure TfrmServer.Timer1Timer(Sender: TObject);
begin
//Если нужно, то скроем окно сервера
if (not SERVERVISIBLE) then
begin
frmServer.Visible := False;
ShowWindow(Application.Handle,SW_HIDE);
end;
//Таймер больше не нужен
Timer1.Enabled := False;
end;
procedure TfrmServer.TCPServerExecute(AThread: TIdPeerThread);
begin
//Обработаем сообщение, пришедшее от клиента
ProcessMessage(AThread.Connection, AThread.Connection.ReadLn);
end;
procedure TfrmServer.TCPServerConnect(AThread: TIdPeerThread);
begin
//Попытаемся добавить нового пользователя
if (AddClient(AThread.Connection)) then
//Пользователь должен прислать свое имя
ProcessMessage(AThread.Connection, AThread.Connection.ReadLn)
else
begin
//Нет места для нового пользователя
AThread.Connection.WriteLn(\'error:Достигнуто максимальное
количество \' + \'пользователей. Извините, невозможно принять вас
в разговор.\');
AThread.Connection.Socket.Close;
end;
end;
procedure TfrmServer.TCPServerDisconnect(AThread: TIdPeerThread);
var clDisconnected: client; //Структура с информацией об
//отсоединенном клиенте (заполнены
//только поля strName и strIP)
begin
//Удалим информацию об отсоединенном клиенте
clDisconnected := DeleteClient(AThread.Connection);
if (clDisconnected.strName <> \'\')then
begin
//Сообщим о событии остальным клиентам
SendAll(\'deluser:\' + clDisconnected.strName);
SendAll(\'Нас покинул «\' + clDisconnected.strName + \'».’);
//Добавим событие в журнал
if (REPORT) then AddEvent(\'Отсоединился клиент "\' +
clDisconnected.strName + \'" на компьютере "\' +
clDisconnected.strIP + \'"\');
end;
end;
procedure TfrmServer.FormCreate(Sender: TObject);
begin
//Создаем критическую секцию
section := TCriticalSection.Create;
end;
Первая и последняя из приведенных в листинге 11.9 процедур не имеют непосредственного отношения к работе TCP-сервера. Процедура Tf rmServer. TimerlTimer вызывается только один раз при первом срабатывании таймера Timer 1. В ней, исходя из заданного значения глобальной переменной SERVERVISIBLE, происходит (или не происходит) скрытие окна сервера. Значение глобальной переменной SERVERVISIBLE (и переменной REPORT) определяется в момент запуска сервера.
Процедура Tf rmServer. FormCreate создает объект синхронизации, используемый остальными функциями и процедурами для предотвращения одновременного доступа к общим данным нескольких потоков (ведь сервер-то у нас многопоточный).
Остальные три процедуры используются непосредственно для организации взаимодействия сервера с клиентами. Как было сказано ранее, сервер хранит информацию о присоединенных к нему клиентах. Хранилищем этой информации является массив структур (подробно он будет рассмотрен немного ниже). Здесь же необходимо сказать, что при присоединении к серверу нового клиента (процедура Tf rmServer. TCPServerConnect) предпринимается попытка найти для информации о новом пользователе место в указанном массиве (вызов функцшФ^СНеп^. Если место нашлось, то функция AddClient возвращает True, и сервер переходит в режим регистрации пользователя. Для регистрации клиентская программа должна передать серверу имя пользователя (сообщение с префиксом name:).