Проблема TCPclient.connected в Delphi - Indy

У меня проблема с функцией IdTCPclient.connected из Indy в Delphi. Я использую среду Indy10 и Delphi2010. Моя проблема заключается в том, что каждый раз, когда я проверяю TCP-соединение с помощью IdTCPclient.connected, возникает исключение с этими ошибками EidSocketError , EidReadTimeOut. Есть ли способ отключить и снова подключить соединение? (например, сбросить соединение).

Примечание. Я установил TCPClient.ReTimeout:= 30000;

Ниже приведена реализованная кодировка для сброса соединения.

if IdTCPclient.connected then
  begin
  IdTCPclient.IOHandler.InputBuffer.Clear;
  IdTCPclient.Disconnect;
  end;
sleep(1000);
try
  IdTCPclient.connect;
  except
    on E: Exception do 
      MessageDlg('Connecting Error: '+E.Message, mtError, [mbOk], 0);
  end;

Но в какой-то момент я получаю исключение, и он вообще не может подключиться. Я не уверен, что я делаю неправильно.

Должен ли я сделать это?

  • Отключить сначала
  • Очистить входной буфер
  • Уничтожить TCP-клиент
  • Повторно создайте новый TCPclient
  • А потом снова подключить

Если это так, может ли кто-нибудь дать мне способ, как это сделать правильно?

Кроме того, в моей кодировке есть еще одна функция для повторного подключения TCP. Это также дает мне исключение. Я проверяю соединение, прежде чем отправить сообщение TCP. Если нет связи, я переподключаюсь пять раз.

result := IdTCPclient.connected
if not result then
  begin
  for k:=0 to 4 do
    beign
    sleep(1000);
    try
      TCPclient.connect;
      except
        on E: Exception do 
          MessageDlg('Connecting Error: '+E.Message, mtError, [mbOk], 0);
      end
    result := TCPclient.connected;
    if result then break;
    end;

С двумя приведенными выше кодами программа довольно хорошо справляется с повторным подключением и сбросом соединения. Но в какой-то момент программа вообще не может переподключиться или сбросить соединение.

  • Что мне делать, когда я получаю исключение? Должен ли я переподключиться из исключения?
  • Как мы строим код, чтобы регулярно проверять соединение?
  • Как мы создаем код, чтобы восстановить соединение, когда оно было потеряно?

С уважением,


person sMah    schedule 02.05.2011    source источник
comment
могу ли я предложить разбить ваш вопрос на несколько более мелких вопросов, на которые можно ответить отдельно.   -  person Sam    schedule 02.05.2011
comment
Может быть похоже на это? stackoverflow.com/questions/38890883/   -  person Z80    schedule 11.08.2016


Ответы (2)


Connected() вообще не должно вызывать никаких исключений. Если это так, то это, вероятно, ошибка. Пожалуйста, предоставьте трассировку стека, показывающую это.

Лучший вариант — просто избегать использования Connected(), когда это возможно. Когда вам нужно выполнить операцию ввода-вывода, просто сделайте это, и пусть Indy вызовет исключение, если произойдет сбой. Затем вы можете справиться с этим в этот момент, например:

try
  IdTCPClient.DoSomething...
except
  on E: EIdException do begin
    Reconnect;
  end;
end;

procedure Reconnect;
var
  k: Integer;
begin
  IdTCPClient.Disconnect;
  if IdTCPClient.IOHandler <> nil then
    IdTCPClient.IOHandler.InputBuffer.Clear;

  for k := 0 to 4 do
  begin
    Sleep(1000);
    try
      IdTCPClient.Connect;
      Exit;
    except
      on E: Exception do
      begin
        MessageDlg('Connecting Error: '+E.Message, mtError, [mbOk], 0);
        if k = 4 then
          raise;
      end;
    end;
  end; 
end;
person Remy Lebeau    schedule 02.05.2011
comment
Как и в случае с OP, я вижу, что Indy10 Connected() вызывает исключение. Трассировка стека здесь i.imgur.com/F9ejbTl.png?1 Нет номеров строк - Прости! - person Roddy; 21.08.2013
comment
@Roddy: Это не имеет смысла. ReadDataFromSource() не вызывается, если сначала сокет не находится в состоянии чтения (TIdSocketHandle.Readable() возвращает True), что может произойти только в том случае, если у сокета есть фактические данные для чтения, или соединение было мягко разорвано узлом. Receive() не должен выходить из строя ни при одном из этих условий. Какое исключение на самом деле вызывается и какой код ошибки сокета сообщается? - person Remy Lebeau; 22.08.2013
comment
EIdSocketError, 10054 соединение сброшено узлом. Это определенно странно, но кажется поправимым. Indy — последний SVN от MJF. У меня есть «рабочее» соединение, а затем выдернуть вилку. Клиент пытается отправить данные и получает EIdSocketError (что нормально), но в обработчике исключений я вызываю Connected(), который также выдает такое же исключение. Чтение обрабатывается другим потоком. - person Roddy; 22.08.2013
comment
Ах, это объясняет, почему Receive() может потерпеть неудачу. И оказывается, что TIdStackBSDBase.Receive() вызывает CheckForSocketError(), но TIdIOHandler вместо этого ожидает обработки ошибки сокета (позволив Connected() отбросить ее). Мне нужно разобраться с этим, я думаю, что классы TIdStack слишком часто вызывают CheckForSocketError(). В любом случае вам не следует звонить Connected(). Вы уже знаете, что сокет не подключен, поскольку вы получаете исключение EIdSocketError/10054, поэтому вызов Connected() будет излишним. - person Remy Lebeau; 22.08.2013
comment
@Remy Однажды (6 лет назад) вы сказали, что Connected() из TIdTCPClient не должен вызывать никаких исключений, но это так. Это старая до сих пор нерешенная ошибка? - person Molochnik; 28.04.2017
comment
@ Молочник, ты говоришь, что последняя версия SVN все еще вызывает исключение? Я думал, что исправил это много лет назад. - person Remy Lebeau; 28.04.2017
comment
@Remy Да, это правда, я всегда использую вашу последнюю (почти) версию SVN. Проверив свой старый код, я обнаружил, что он всегда содержит Connected в блоках try-except. Теперь я попытался их устранить, но исключения все еще случаются. - person Molochnik; 28.04.2017

перед подключением убедитесь, что пассивное логическое значение idftp равно false, когда вам нужно передать файл, измените его на true с опцией двоичного файла

person Sami Echikh    schedule 18.09.2016