Inter-process communication

孤者浪人 提交于 2019-11-27 07:40:56

You can do it more simply, since you're just trying to find out if one app is running from another one. As long as they're running on the same machine by the same user, you can have X simply use FindWindow() to see if Y is currently running. Just make sure you give Y a meaningful name (in the sample below, it's TXMLFormatterForm):

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

You can also use Y's window caption (title), as long as you're sure it's distinct:

XMLWindow := FindWindow(nil, 'Workshop Alex's XML Formatter');

Have a look at my IPC at:

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

It is fast, free and has a setable timeout, so you can set it to a very small amount (50ms for example). Because it is very fast (typical message cycle request -> process -> response takes less than 1ms, around 0.1ms) you can have very small timeouts. It has client server build into it, so many clients are no problem. It runs threaded with task pool behind so it does not freeze your program and it has very flexible data packets to ease writing / reading the data.

As already said you can even check with other means if the debugger is running.

  • Check for process
  • Check for main window of the process
  • Use a Mutex
  • ...

You could have X write its output to a memory-mapped file - Y can retrieve the data if it is running. This way X does not care whether or not Y is up.

X could write some kind of control info at a known location (eg. store the offsets of last 1000 written XMLs starting at offset 0 in the mapped file) and use the rest of the file as a circular buffer for the raw data.

If you need Y to be the determining factor for actions in X, have Y create the mapped file, and then use its presence/absence as a check on the data production on the X side of the 'channel'. There is example code for creator and second user here.

A.Bouchez

Named pipes are fast, because they are based on memory mapped files, for their implementation. What could be slow is the timeout in case of server failure...

If you need to have fast response on the same computer, why don't you use good old GDI messages?

You can use these messages, even with no User Interface or visual form, in plain console or background service applications (in case of a service application, the security settings must specify that this service must interact with the desktop, that is, must be able to receive and send messages).

The trick is to handle WM_COPYDATA messages. See for example our TSQLRestClientURIMessage class, and the ExportServerMessage/AnswerToMessage methods of TSQLRestServer, as implemented in http://synopse.info/fossil/finfo?name=SQLite3/SQLite3Commons.pas

In practice, I found out that GDI messages are much faster than named pipes for small amount of data (up to 64 KB or such per message).

You have alternatives in Looking for an alternative to windows messages used in inter-process communication

Here are some real data about speed, according to diverse client/server investigation.

All benchmarks were run locally on one computer. You can achieve more than 15000 queries per second on direct access, 4300 queries per second on HTTP/1.1 remote access. This was benchmarked on a Notebook using a Centrino2 CPU, with AntiVirus ON.

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

This benchmark tests both client and server speed, and is not multithreaded (even if our framework is multi-thread safe).

So you can guess that, for a 4 KB data block of JSON content for each request:

  1. The direct access (like your dll approach) is the fastest, and less resource consuming.
  2. Then GDI messages.
  3. Then named pipes.
  4. Then FastCGI and HTTP (depending on your web server for FastCGI, the HTTP classes are very low consuming).

Keep alive connections are HTTP/1.1 connections, and multi connect is plain HTTP/1.0, with a new connection for every request. Multi-connect is not so bad, because from the server point of view, we used an efficient Thread Pool based on I/O completion ports.

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

Use memory-mapped files. They are great for your particular tasks. And our MsgConnect with it's MMF transport will come to rescue if you don't have time or intention to implement custom scheme.

I would go the memory mapped files direction, but I would not implement directly in the code path..instead I would go through an intermediate object that would perform the writing to the memory mapped file, this way it could be replaced with one that just discarded the data if it was not in place.

When the program first starts (or is told to check via a configuration change) the system would either create the stub "do nothing" or the "log via memory mapped files" object. This also gives you the capability of adding a later debugger when the need arises...such as a UDP logger for network logging, etc.

You can use the "FindWindow" call to see if your debugger is running.

If you are willing to use temporary file as transport, then it will be easy

  1. Both programs register a same custom message on start up MsgAppNotifyID := RegisterWindowMessage(......);

  2. Program Y must have codes to handle the custom message using SetWindowLong or anything equivalent

  3. Program X, using FindWindow to see if program Y is running or not

  4. Program X, If Y is running, Create a temp file on known location/directory of both end using consistent file name such as XXYY1234 (XXYYn) format where 1234=n

  5. Program X, use BroadcastSystemMessage to signal program Y NotifyRecipients := BSM_APPLICATIONS; BroadcastSystemMessage(BSF_IGNORECURRENTTASK or BSF_POSTMESSAGE or BSF_FORCEIFHUNG, @NotifyRecipients, MsgAppNotifyID, any custom value, n);

  6. Program y, process above message using WParam as n and reconstruct the file for process

Cheers Good luck

running a TCP server which just on a connect (as a trigger) is really fast and should do what you want

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!