Nano Hash - криптовалюты, майнинг, программирование

Indy, Access Violatio, когда слишком много подключений

У меня три вопроса:

  1. можно ли уничтожить IdTCPServer по множеству подключений? Я попытался протестировать свое приложение, и когда у меня есть несколько подключений - оно работает очень хорошо (даже несколько дней), но когда иногда количество подключений увеличивается, приложение дает нарушение доступа. Я написал приложение, которое имитирует 50 клиентов, постоянно отправляющих данные (только со сном (200)). И в этой ситуации IdTCPServer дает исключения? Мое приложение получает информацию от клиентов по событию onExecute и изменяет таблицу баз данных с помощью классов TidNotify и TIdSync. Я считаю, что он защищает перекрестные соединения потоков? Отправку информации клиентам делает TTimer (это только сейчас, поменяю на другой поток). Достаточно ли использовать в этой ситуации специальную защиту или что-то в этом роде:

    type
      PClient = ^TClient;
      TClient = record
        Activity_time:TDateTime;
        AContext: TIdContext;
      end;
    ...
    list := server.Contexts.LockList;
    try
     for i := 0 to list.Count - 1 do
      with TIdContext(list[i]) do
      begin
    
        if SecondsBetween(now(), PClient(data)^.activity_time) > 6 then
        begin
          Connection.IOHandler.Close;
          Continue;
        end;
        try
          Connection.IOHandler.writeln('E:');
        Except
          Connection.IOHandler.Close;
        end;
      end;
    finally
      server.Contexts.UnlockList;
    end;
    

2. Есть ли простой способ отказаться от соединения, когда сервер занят (я думаю, что моя база данных не сложна (100 строк, только одна строка модифицируется одним соединением), но, может быть, это способ сохранить стабильность сервера?

3. Я знаю, что этот вопрос повторялся много раз, но я не нашел удовлетворительного ответа: как защитить приложение, чтобы избежать исключения сообщений: «Соединение закрыто корректно» и «Соединение сброшено узлом»?

Спасибо за все советы

02.01.2013

  • Какую версию Indy вы используете? 02.01.2013

Ответы:


1

можно ли уничтожить IdTCPServer по множеству подключений?

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

type
  PClient = ^TClient;
  TClient = record
    Activity_time: TDateTime;
    Heartbeat_time: TDateTime;
    AContext: TIdContext;
  end;

procedure TForm1.serverConnect(AContext: TIdContext);
var
  Client: PClient;
begin
  New(Client);
  Client^.Activity_time := Now();
  Client^.Heartbeat_time := Client^.Activity_time;
  AContext.Data := TObject(Client);
end;

procedure TForm1.serverDisconnect(AContext: TIdContext);
var
  Client: PClient;
begin
  Client := PClient(AContext.Data);
  AContext.Data := nil;
  if Client <> nil then Dispose(Client);
end;

procedure TForm1.serverExecute(AContext: TIdContext);
var
  Client: PClient;
  dtNow: TDateTime;
begin
  Client := PClient(AContext.Data);
  dtNow := Now();

  if SecondsBetween(dtNow, Client^.Activity_time) > 6 then
  begin
    AContext.Connection.Disconnect;
    Exit;
  end;

  if SecondsBetween(dtNow, Client^.Heartbeat_time) > 2 then
  begin
    AContext.Connection.IOHandler.WriteLn('E:');
    Client^.Heartbeat_time := dtNow;
  end;

  if AContext.Connection.IOHandler.InputBufferIsEmpty then
  begin
    if not AContext.Connection.IOHandler.CheckForDataOnSource(100) then
      Exit;
  end;

  // process incoming data as needed ...

  Client^.Activity_time := Now();
end;

Это простой способ отказаться от соединения, когда сервер занят (я думаю, что моя база данных не сложна (100 строк, только одна строка модифицируется одним соединением), но, может быть, это способ сохранить стабильность сервера?

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

Другой вариант — вызвать метод StopListening() сервера, когда сервер занят, чтобы новые соединения больше не могли достичь сервера, а затем вызвать метод StartListening() сервера, когда вы снова будете готовы принимать новых клиентов. Существующие клиенты, которые уже подключены, не должны быть затронуты, хотя я еще не пробовал это сам.

Я знаю, что этот вопрос повторялся много раз, но я не нашел удовлетворительного ответа: как защитить приложение, чтобы избежать исключения сообщений: «Соединение закрыто изящно» и «Соединение сброшено узлом»?

Не следует их избегать. Пусть они случаются, это нормальные ошибки. Если они происходят внутри событий сервера, просто позвольте серверу нормально обрабатывать их для вас. Вот как TIdTCServer предназначен для использования. Если они происходят вне событий сервера, например, в вашем таймере, просто оберните операции сокета в блок try/except и двигайтесь дальше.

02.01.2013
  • Спасибо. Но serverExecute срабатывает при поступлении данных. Но мне нужно остановить (закрыть) соединение с клиентом, когда данные не поступают от клиента в определенное время. Поэтому я думаю, что не могу использовать serverExecute в этой ситуации и ищу разные (может быть, странные) решения. 03.01.2013
  • @Artik: событие OnExecute работает НЕ так. Он запускается в непрерывном цикле на время существования соединения. Как только OnExecute выходит, он тут же снова срабатывает, вне зависимости есть новые данные или нет. Код внутри обработчика OnExecute отвечает за фактическое ожидание новых данных по мере необходимости. Вот где тайм-ауты вступают в игру. Вы можете выполнить ожидание данных по времени и проверить тайм-аут простоя в том же коде. Я обновил пример в своем ответе, чтобы продемонстрировать это. 03.01.2013
  • Извините, только еще один вопрос: как безопасно передать значение из основного потока в поток Indys - я имею в виду метод OnExcecute, чтобы отправить его клиенту в зависимости от ситуации в приложении? Еще раз спасибо за вашего пациента. 03.01.2013
  • См. это недавнее обсуждение, которое демонстрирует именно это: -сервер 04.01.2013
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

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

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..