Отправка и получение одновременно с TIdTCPServer

#delphi #indy #tcpserver #duplex

#delphi #indy #tcpserver #двусторонний

Вопрос:

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

Как дождаться определенной последовательности при вводе и одновременно отправить некоторые данные одному и тому же клиенту? Мне не нужна последовательность команд-ответов, но мне нужно:

  • постоянно отправляйте текущие данные
  • при получении отредактированных данных обратно
  • и получать команды и предоставлять ответы на них.

Например, если мы ожидаем CR-LF:

 procedure TSocketServer._serverExecute(AContext: TIdContext);
var
  msg: string;
begin
  msg := AContext.Connection.IOHandler.ReadLn();
  //Here we are only if CRLF was detected.
  //How to send while we are waiting?
  _log(msg);
end;
  

Комментарии:

1. Откройте несколько подключений. Для этого требуется несколько компонентов TCP.

2. Если подумать, вам может сойти с рук только 1 TCP-сервер, поскольку он принимает соединения от нескольких клиентов. Но на стороне клиента вам понадобятся два и какой-то способ сообщить серверу, что есть что.

3. Установите свойство timeout для IOHander, чтобы функция ReadLn продолжалась через некоторое время, даже если байты не были прочитаны.

4. В качестве альтернативы, перед вызовом IOHandler.ReadLn() вызовите IOHandler.CheckForDataOnSource() с таймаутом и проверьте с помощью IOHandler.InputBufferIsEmpty()

5. @Remy Действительно, существует множество способов, я предлагал одну идею. Но я смотрел на это с точки зрения брандмауэра — чем меньше портов открывать, тем проще.

Ответ №1:

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

Существует несколько различных способов обработки отправки:

  • используйте отдельные потоки для чтения и отправки. Например, пусть OnExecute поток обрабатывает все чтения и использует другой рабочий поток для обработки всей отправки. Если OnExecute получает входящую команду, которая должна отправить ответ, передайте данные ответа отправляющему потоку (потокобезопасным способом), чтобы он мог отправить ответ, когда это безопасно, между нежелательными сообщениями.

  • пусть OnExecute поток обрабатывает как чтение, так и отправку. Непрерывно отправляйте исходящие нежелательные данные по мере необходимости и периодически проверяйте входящие данные, используя методы IOHandler.InputBufferIsEmpty() и IOHandler.CheckForSourceOnData() , чтобы определить, когда требуется прочитать входящее сообщение.

  • в противном случае, как предложил Джерри Додж в комментариях, просто используйте отдельные соединения, одно для данных ответа на команду и одно для нежелательных данных.