I am trying to figure out what methods are available for IPC in D, mainly named pipes. I know that std.process contains functions for unnamed pipes from a related process, although I am looking more at ipc with unrelated processes that are bi-directional. I was thinking that I may need to end up using local sockets, or look into shared memory.
Is there any examples to do this?
On Unix, you can create a unix domain socket with std.socket similarly to a TCP socket, but local only. Here's some example code:
// SERVER
import std.socket;
void main() {
auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
listener.bind(new UnixAddress("/home/me/uds"));
listener.listen(10);
/*while(1)*/ {
auto soc = listener.accept();
soc.send("cool\n");
soc.close();
}
listener.close();
import core.sys.posix.unistd;
unlink("/home/me/uds");
}
And the client:
void main() {
auto soc = new Socket(AddressFamily.UNIX, SocketType.STREAM);
soc.connect(new UnixAddress("/home/me/uds"));
import std.stdio;
char[1222] buf;
writeln(buf[0 .. soc.receive(buf)]);
soc.close();
}
The only thing they have to know about each other is what the messages mean (of course), and the filesystem path to the socket.
Unix also does named pipes, but they aren't bidirectional like the unix domain socket (or a Windows named pipe)
If you do want a unix named pipe, they are called FIFO files and are made with the mkfifo system API function. You can access it with import core.sys.posix.sys.stat;
then use it the same way as in C: pass it a string and mode to create the file, don't forget to check the return value, then read/write it with the regular Unix file functions, e.g. read
, write
, close
, all from import core.sys.posix.unistd;
. Refer to the C documentation for these functions, e.g. man 2 read
or man 3 mkfifo
if you are on Linux, or just search the web for those pages.
But I think the unix domain socket is what you're looking for and it works basically the same as any other socket, as seen in my example above.
Windows does things differently, and the D standard library doesn't even include the OS API function prototypes.
http://msdn.microsoft.com/en-us/library/windows/desktop/aa365150%28v=vs.85%29.aspx
You create a named pipe with that function, giving it a path name which other processes can use (similar to a Unix domain socket, but not in the unified filesystem). Then you use the CreateFile function to open the pipe and afterwards, you can talk to it like any other file.
There's two ways to get function prototypes so you can call these functions from D. One is to copy/paste them yourself, like this:
extern(Windows)
HANDLE CreateNamedPipeA(
LPCTSTR lpName,
DWORD dwOpenMode,
DWORD dwPipeMode,
DWORD nMaxInstances,
DWORD nOutBufferSize,
DWORD nInBufferSize,
DWORD nDefaultTimeOut,
LPSECURITY_ATTRIBUTES lpSecurityAttributes
);
First, import core.sys.windows.windows;
to get the basic Windows type definitions, then just add thigns like that to your file. It is the same as MSDN, just with things like In removed. (you could prolly just change them to D's in
keyword too).
The big thing is the addition of A or W to the name. This is mentioned at the bottom of the Microsoft docs about Unicode vs ANSI name. The A versions take ascii strings. The W version take utf-16, wstring
in D. The W version is recommended, but the A versions are a bit easier to use in some cases.
Or, you can download pre-made win32 bindings from here: https://github.com/AndrejMitrovic/DWinProgramming/tree/master/WindowsAPI and use them when building.
If you just need a couple functions, I prefer to copy/paste to avoid the dependency, but if you're doing a lot of Windows API work, download the complete bindings.
I wrote a cross-platform terminal emulator in D that makes use of these techniques: https://github.com/adamdruppe/terminal-emulator
The detachable portion uses a unix domain socket server: https://github.com/adamdruppe/terminal-emulator/blob/master/detachable.d
The attachable portion is a UDS client https://github.com/adamdruppe/terminal-emulator/blob/master/attach.d
The Windows emulator core uses a specialized named pipe to do my own async 'anonymous' pipe, not your use case, but shows how the functions can be called: https://github.com/adamdruppe/terminal-emulator/blob/master/terminalemulator.d
Shared memory is another thing you can do but expect little help from the D library, you'll have to use the OS functions. But it isn't hard, at least the function prototypes are there on Unix: import core.sys.posix.sys.shm and use the functions the same as in C.
I've never actually done it on Windows, but a quick search says yo can just make a memory-mapped file: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366551%28v=vs.85%29.aspx
which maybe, just maybe will get help from phobos: http://dlang.org/phobos/std_mmfile.html but again, I've never actually tried this. When I needed shared memory, I just did the shmget etc. Unix functions (this was in my simpledisplay.d https://github.com/adamdruppe/arsd/blob/master/simpledisplay.d which uses it to talk to the X server).
Bottom line though, is Unix domain sockets are basically the same as TCP sockets and Phobos' std.socket helps out.
Everything else is done the same as you would in C.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With