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

Всегда рекомендуется выполнять все задачи отправки/получения в 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;

person Paul    schedule 12.04.2019    source источник
comment
Откройте несколько подключений. Для этого требуется несколько компонентов TCP.   -  person Jerry Dodge    schedule 12.04.2019
comment
Если подумать, вы можете обойтись только одним TCP-сервером, поскольку он принимает соединения от нескольких клиентов. Но на стороне клиента вам понадобятся два и какой-то способ сообщить серверу, что есть что.   -  person Jerry Dodge    schedule 12.04.2019
comment
Установите свойство тайм-аута IOHander, чтобы функция ReadLn продолжала работу через некоторое время, даже если байты не читаются.   -  person nolaspeaker    schedule 12.04.2019
comment
В качестве альтернативы перед вызовом IOHandler.ReadLn() вызовите IOHandler.CheckForDataOnSource() с тайм-аутом и проверьте с помощью IOHandler.InputBufferIsEmpty()   -  person Remy Lebeau    schedule 12.04.2019
comment
@JerryDodge Но на стороне клиента вам понадобятся два порта и какой-то способ сообщить серверу, что есть что - вы можете заставить сервер прослушивать 2 разных порта. Затем клиент может открывать подключения к обоим портам по мере необходимости.   -  person Remy Lebeau    schedule 12.04.2019
comment
@Remy Действительно, есть множество способов, я предлагал одну идею. Но я смотрел на это с точки зрения брандмауэра — чем меньше портов открывать, тем проще.   -  person Jerry Dodge    schedule 12.04.2019


Ответы (1)


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

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

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

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

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

person Remy Lebeau    schedule 12.04.2019