Межпроцессного взаимодействия - PullRequest
14 голосов
/ 03 ноября 2010

У меня есть два приложения: X и Y.
X - основное приложение, которое обрабатывает много XML-файлов. Его история насчитывает более 10 лет, и полдюжины методов использовались для хранения, обработки и обработки этих файлов XML.
Y - это разрабатываемый мной инструмент отладки, который может обрабатывать и отображать файлы XML в более читабельная форма. По сути, он просто имеет коллекцию таблиц стилей, которые будут определять формат XML, и если он распознает формат, он преобразует XML в HTML, который отображается в компоненте TWebBrowser.

Проблема:
Когда Y активен, я хочу, чтобы X отправил любой XML, который он передает, Y для отображения. Но только когда Y бежит! Если Y не работает, X просто не будет ничего делать.
Обнаружение Y должно быть выполнено в любой момент и должно быть быстрым. Я рассмотрел использование связи по TCP / IP, но задержка, вызванная отсутствием Y, слишком велика. Тем более, что много XML иногда обрабатывается. Та же проблема с именованными каналами и аналогичными сетевыми решениями. Мне нужно быстро определить, работает ли и доступен ли Y, и если да, быстро отправить XML, а затем продолжить X.
Я также решил сделать Y приложением на основе COM или, возможно, добавить DLL на основе COM с события, которые позволили бы межпроцессное взаимодействие. Решение DLL было бы интересно, так как оно предоставляло бы метод X для загрузки файла XML, а затем отправлял бы событие Y для обработки XML. Это, кажется, лучший вариант , хотя мне также нужно проверить, зарегистрирована ли DLL или нет. Если нет, то X даже не может вызвать его!
Приложение X также будет использоваться клиентами, которые не получат Y или дополнительную DLL, поэтому в большинстве случаев DLL не будет зарегистрирована. (Как я уже сказал, это должно помочь во время отладки ...)

Но, может быть, есть другие варианты? TCP / IP слишком медленный, COM слишком сложный.


X и Y будут работать в одной системе. Или только X будет в системе, а Y полностью отсутствует.


Об использовании файлов, отображаемых в память ... Хотя практично, я должен иметь в виду, что в большинстве случаев Y не будет работать, поэтому MMF будет тратить память. XML-данные могут иметь размер до 4 МБ в X, поэтому наличие нескольких блоков такого размера в памяти немного излишне. Его можно использовать для отправки сообщений о состоянии между X и Y, но иногда с приложением X возникает проблема с памятью. И хотя MMF может быть подключен к физическому файлу, я стараюсь вообще не писать никаких временных файлов. < br /> Это хорошее решение, но я боюсь, что оно недостаточно.


Некоторые дополнительные объяснения приведены в порядке, я думаю. Приложение X - это приложение, которое будет использоваться в течение нескольких часов, при этом пользователи выполняют множество действий, которые преобразуются во множество обрабатываемых XML-данных. Приложение X является настольным приложением, которое взаимодействует с несколькими веб-приложениями (REST), веб-службами (SOAP) и другими приложениями, и большинство из них - через XML.
Приложение Y предназначено только для просмотра процессов, запущенных X , В основном, X работает в течение 20 минут, а Y всплывает. С этого момента X должен начать посылать XML на Y, пока Y снова не исчезнет или пока X не завершится. В большинстве случаев Y просто запускается, чтобы захватить только небольшую часть запущенных задач, и, возможно, он даже запускается несколько раз. Но я могу думать обо всем в неправильном направлении. Возможно, X должен быть сервером, где Y регистрируется на нем ... Это не реальная проблема, когда Y не может найти X. Но X не находит Y не может привести к задержкам или другим проблемам ...

Ответы [ 9 ]

11 голосов
/ 03 ноября 2010

Посмотрите на мой IPC по адресу:

http://www.cromis.net/blog/downloads/cromis-ipc/

Это быстрый, бесплатный и настраиваемый тайм-аут, так что вы можете установить его на очень небольшое количество (50 мс дляпример).Поскольку это очень быстро (типичный запрос цикла сообщений -> процесс -> ответ занимает менее 1 мс, около 0,1 мс), вы можете иметь очень малые тайм-ауты.В него встроен клиент-сервер, поэтому у многих клиентов проблем нет.Он работает с многопоточным пулом задач, поэтому он не замораживает вашу программу и обладает очень гибкими пакетами данных для облегчения записи / чтения данных.

Как уже говорилось, вы можете проверить другими средствами, работает ли отладчик.

  • Проверка процесса
  • Проверка главного окна процесса
  • Использование Mutex
  • ...
6 голосов
/ 03 ноября 2010

Вы можете сделать так, чтобы X записывал свой вывод в файл с отображением в памяти - Y может получить данные, если он работает.Таким образом, X не волнует, поднялся ли Y или нет.

X может записать некоторую управляющую информацию в известном месте (например, сохранить смещения последних 1000 записанных XML-файлов, начиная со смещения 0 в отображенном файле) и использовать оставшуюся часть файла в качестве циклического буфера длянеобработанные данные.

Если вам нужно, чтобы Y был определяющим фактором для действий в X, попросите Y создать сопоставленный файл, а затем использовать его наличие / отсутствие в качестве проверки для производства данных на стороне Xканал'.Пример кода для создателя и второго пользователя здесь .

5 голосов
/ 03 ноября 2010

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

var
  XMLWindow: HWnd;
begin
  XMLWindow := FindWindow('TXMLFormatterForm', nil);
  if XMLWindow > 0 then
    // Y is running
end;

Вы также можете использовать заголовок окна Y (заголовок), если вы уверены, что он различен:

XMLWindow := FindWindow(nil, 'Workshop Alex's XML Formatter');
4 голосов
/ 03 ноября 2010

Именованные каналы быстры, потому что они основаны на файлах с отображенной памятью для их реализации. Что может быть медленным, это тайм-аут в случае сбоя сервера ...

Если вам нужен быстрый ответ на том же компьютере, почему бы вам не использовать старые добрые сообщения GDI?

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

Хитрость заключается в обработке сообщений WM_COPYDATA. Посмотрите, например, наш класс TSQLRestClientURIMessage и методы ExportServerMessage / AnswerToMessage TSQLRestServer, реализованные в http://synopse.info/fossil/finfo?name=SQLite3/SQLite3Commons.pas

На практике я обнаружил, что сообщения GDI намного быстрее, чем именованные каналы, для небольшого объема данных (до 64 КБ или около того на сообщение).

У вас есть альтернативы в Ищете альтернативу сообщениям Windows, используемым в межпроцессном взаимодействии

2 голосов
/ 04 ноября 2010

Вот некоторые реальные данные о скорости, согласно разнообразным исследованиям клиент / сервер.

Все тесты проводились локально на одном компьютере.Вы можете выполнить более 15000 запросов в секунду при прямом доступе, 4300 запросов в секунду при удаленном доступе HTTP / 1.1.Это было оценено на ноутбуке с процессором Centrino2 с включенным AntiVirus.

2.5. Client server access: 
  - Http client keep alive: 3001 assertions passed
     first in 7.87ms, done in 153.37ms i.e. 6520/s, average 153us
  - Http client multi connect: 3001 assertions passed
     first in 151us, done in 305.98ms i.e. 3268/s, average 305us
  - Named pipe access: 3003 assertions passed
     first in 78.67ms, done in 187.15ms i.e. 5343/s, average 187us
  - Local window messages: 3002 assertions passed
     first in 148us, done in 112.90ms i.e. 8857/s, average 112us
  - Direct in process access: 3001 assertions passed
     first in 44us, done in 41.69ms i.e. 23981/s, average 41us
  Total failed: 0 / 15014  - Client server access PASSED

Этот тест тестирует скорость клиента и сервера и не является многопоточным (даже если наша среда является многопоточной).

Так что вы можете догадаться, что для 4 КБблок данных содержимого JSON для каждого запроса:

  1. Прямой доступ (как и в случае использования dll) является самым быстрым и требует меньше ресурсов.
  2. Тогда сообщения GDI.
  3. Затем именованные каналы.
  4. Затем FastCGI и HTTP (в зависимости от вашего веб-сервера для FastCGI HTTP-классы потребляют очень мало).

Поддерживаются живые соединения HTTP / 1.1Соединения, а мультиконнект - простой HTTP / 1.0, с новым соединением для каждого запроса.Multi-connect не так уж и плох, потому что с точки зрения сервера мы использовали эффективный пул потоков на основе портов завершения ввода / вывода.

См. http://synopse.info/forum/viewtopic.php?id=90

1 голос
/ 03 ноября 2010

Я бы пошел в направлении к отображенным в память файлам, но я бы не реализовал непосредственно в пути к коду .. Вместо этого я бы прошел промежуточный объект, который выполнял бы запись в отображенный в память файл, таким образом, его можно было бы заменить натот, который просто отбрасывал данные, если их не было на месте.

Когда программа запускается впервые (или получает указание проверить через изменение конфигурации), система либо создает заглушку "ничего не делать", либо "журнал"через память сопоставленных файлов "объекта.Это также дает вам возможность добавить более поздний отладчик, когда возникнет такая необходимость ... например, UDP-регистратор для сетевого журналирования и т. Д.

Вы можете использовать вызов «FindWindow», чтобы проверить, работает ли ваш отладчик..

1 голос
/ 03 ноября 2010

Использовать отображенные в памяти файлы. Они отлично подходят для ваших конкретных задач. И наш MsgConnect с его транспортом MMF придет на помощь, если у вас нет времени или намерения реализовать собственную схему.

0 голосов
/ 04 ноября 2010

работает TCP-сервер, который просто подключается (как триггер) очень быстро и должен делать то, что вы хотите

0 голосов
/ 03 ноября 2010

Если вы хотите использовать временный файл в качестве транспорта, тогда будет легко

  1. Обе программы регистрируют одно и то же настраиваемое сообщение при запуске MsgAppNotifyID: = RegisterWindowMessage (......);

  2. Программа Y должна иметь коды для обработки пользовательского сообщения, используя SetWindowLong или что-либо эквивалентное

  3. Программа X, использующая FindWindow для просмотраесли программа Y запущена или нет

  4. Программа X, если Y запущена, создайте временный файл в известном местоположении / каталоге обоих концов, используя согласованное имя файла, например, в формате XXYY1234 (XXYYn)где 1234 = n

  5. Программа X, используйте BroadcastSystemMessage для сигнализации программы Y NotifyRecipients: = BSM_APPLICATIONS;BroadcastSystemMessage (BSF_IGNORECURRENTTASK или BSF_POSTMESSAGE или BSF_FORCEIFHUNG, @NotifyRecipients, MsgAppNotifyID, любое пользовательское значение, n);

  6. Программа y, обработайте вышеуказанное сообщение, используя WParam как n, и восстановите 1025 для восстановления и восстановления25*

ура Удачи

...