Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
KANSoftWare

Организация одноканальной коммуникации с рассылкой сообщений через интернет на основе Indy и Delphi

Delphi , Интернет и Сети , TCP/IP

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

Основная проблема

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

Решение на основе Indy

Важное замечание: протоколы TCP/IP не поддерживают вещание в прямом смысле слова. Вместо этого вам нужно будет обрабатывать каждого получателя по отдельности, что может быть выполнено непосредственно с помощью события OnExecute компонента сервера.

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

Пример кода на Object Pascal (Delphi)

type
  TDataQueue = class(TInterfacedObject, IInterface)
  private
    FQueue: TThreadSafeQueue;
    constructor Create; override;
    destructor Destroy; override;
    procedure AddToQueue(const AData: TStream); safecall;
  public
    function GetFromQueue(out Result: TStream): boolean; safecall;
  end;

constructor TDataQueue.Create;
begin
  inherited Create;
  FQueue := TThreadSafeQueue.Create(TStream);
end;

destructor TDataQueue.Destroy;
begin
  FQueue.Free;
  inherited Destroy;
end;

procedure TDataQueue.AddToQueue(const AData: TStream);
begin
  FQueue.Push(AData);
end;

function TDataQueue.GetFromQueue(out Result: TStream): boolean;
begin
  Result := nil;
  if not FQueue.Count = 0 then
    Result := (FQueue.Pop as TStream)
  Result <> nil; // Возвращаем истину, если данные были успешно извлечены
end;

procedure TServerForm.IdTCPServer1Execute(AContext: TIdContext);
var
  DataBuffer: TMemoryStream;
begin
  inherited;
  AContext.Connection.IOHandler.ReadDirect(DataBuffer, AContext.Connection.IOHandler.InputBufferSize);
  with TDataQueue.Create(nil) do try
    AddToQueue(DataBuffer);
    for var Client in IdTCPServer1.Contexts do
      if Assigned(Client.Connection) then begin
        with TDataQueue.Create(nil) do try
          Client.DataQueue := self;
          while GetFromQueue(ResultStream) do begin
            Client.Connection.IOHandler.Write(ResultStream);
            ResultStream.Free;
          end;
        finally
          Client.DataQueue.Free;
        end;
      end;
  finally
    Free;
  end;
end;

procedure TServerForm.FormCreate(Sender: TObject);
begin
  IdTCPServer1.Contexts.ListChanged := True;
  IdTCPServer1.OnClientConnect := OnClientConnect;
  IdTCPServer1.OnClientDisconnect := OnClientDisconnect;
end;

procedure TServerForm.OnClientConnect(AContext: Pointer);
var
  Client: Pointer;
begin
  Client := GetMemory(SizeOf(TClient));
  with Client^ do begin
    DataQueue := nil;
    // Здесь может быть код для инициализации клиентской информации
  end;
  IdTCPServer1.Contexts.Add(Client);
end;

procedure TServerForm.OnClientDisconnect(AContext: Pointer; AConnection: Pointer);
var
  Client: Pointer;
begin
  Client := AContext;
  if Assigned(Client^) then begin
    if Assigned(Client^.DataQueue) then
      Client^.DataQueue.Free;
    SetLength(Client, 0);
    IdTCPServer1.Contexts.Remove(AContext);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  // Инициализация формы и сервера
end;
// Этот код представляет собой основу для обработки входящего потока данных и его последующего распространения на всех клиентов,
взаимодействие с приватными очередями для каждого клиента, что позволяет избежать блокировки основного потока чтения.

Заключение

Используя этот подход, вы можете реализовать одноканальный ввод потоковых данных от одного источника к множеству получателей без существенных задержек для главного потока чтения. Это эффективный метод работы с TCP-сервером и компонентами Indy в среде Delphi, который позволяет создавать многоточечные связные приложения.


Примечание: В примере выше используется механизм безопасных очередей для реализации параллельной передачи данных между клиентом-источником и множеством получателей. Это общий образец кода, как может быть организована такая система в вашем приложении на Delphi.

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

Создано по материалам из источника по ссылке.

В статье обсуждается метод обеспечения передачи данных от одного клиента ко многим в многосервисных веб-приложениях и играх, используя `Indy 10` в среде Delphi для реализации сервера с поддержкой одновременной передачи потоковых данных множеству подключе


Комментарии и вопросы

Получайте свежие новости и обновления по Object Pascal, Delphi и Lazarus прямо в свой смартфон. Подпишитесь на наш Telegram-канал delphi_kansoftware и будьте в курсе последних тенденций в разработке под Linux, Windows, Android и iOS




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.


:: Главная :: TCP/IP ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-12-22 20:14:06
2025-03-12 07:23:08/0.011806964874268/0