Создание клиент-серверной архитектуры на TCP в Delphi с использованием Indy
Введение:
Разработка клиент-серверных приложений на языке Object Pascal в среде Delphi часто включает работу с сетевыми библиотеками. Одной из наиболее популярных библиотек для работы с сетью является Indy, которая предоставляет широкие возможности для создания TCP/IP-клиентов и серверов.
Проблема пользователя:
Пользователь столкнулся с проблемой при попытке деактивизации TCPServer в приложении Delphi XE3, используя компоненты Indy 10. При подключенном клиенте отключение сервера приводило к тому, что клиент разъединялся, но сам сервер переставал отвечать на запросы.
Решение проблемы:
В ходе решения было выявлено несколько ошибок в коде пользователя:
Необходимо использовать глобальный объект GStack для доступа к стеку сокетов Indy, а не создавать экземпляр класса TIdStack.
События компонента TCPServer, такие как OnConnect, OnDisconnect, и OnExecute, выполняются в отдельных потоках. Для безопасного доступа к UI-контролам необходимо использовать механизмы синхронизации.
Вызов Application.ProcessMessages() не должен использоваться вне основного потока пользовательского интерфейса.
Пример исправленного кода:
procedure TfrmMain.btnConnectClick(Sender: TObject);
begin
if not TCPServer.Active then begin
TCPServer.Bindings.Clear;
with TCPServer.Bindings.Add do
begin
IP := '192.168.1.11';
Port := StrToInt(edtPort.Text);
end;
TCPServer.Active := True;
end;
end;
procedure TfrmMain.btnDisconnectClick(Sender: TObject);
begin
TCPServer.Active := False;
end;
procedure TfrmMain.TCPServerConnect(AContext: TIdContext);
var
Msg: string;
begin
Msg := 'Connected - ' + GStack.HostByAddress(AContext.Binding.PeerIP) + ' (' + AContext.Binding.PeerIP + ')';
TThread.Queue(nil,
procedure
begin
memLog.Lines.Add(Msg);
end
);
end;
procedure TfrmMain.TCPServerDisconnect(AContext: TIdContext);
var
Msg: string;
begin
Msg := 'Disconnected - ' + GStack.HostByAddress(AContext.Binding.PeerIP) + ' (' + AContext.Binding.PeerIP + ')';
TThread.Queue(nil,
procedure
begin
memLog.Lines.Add(Msg);
end
);
end;
procedure TfrmMain.TCPServerExecute(AContext: TIdContext);
begin
// Здесь должна быть логика коммуникации с клиентом
end;
Выводы:
При работе с компонентами Indy важно помнить о правильном использовании потоков и синхронизации доступа к UI-элементам. Использование глобального объекта GStack вместо создания экземпляра класса TIdStack позволяет избежать ошибок, связанных с неправильным обращением к стеку сокетов.
Этот пример можно использовать в качестве основы для создания простого сервера на TCP в Delphi, который будет проверять состояние клиентов. Ошибки в изначальном коде были исправлены согласно рекомендациям эксперта по Indy.
Создание клиент-серверной архитектуры на TCP/IP для приложений Delphi с использованием компонентов Indy 10 и решение проблемы отключения сервера без завершения запросов в контексте работы потоков.
Комментарии и вопросы
Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS