在D中创建命名管道?

在D中创建命名管道?,d,D,我正试图找出什么方法可以用于D中的IPC,主要是命名管道。我知道std.process包含来自相关进程的未命名管道的函数,尽管我更多地关注具有双向的不相关进程的ipc。我想我可能需要使用本地套接字,或者查看共享内存 有这样做的例子吗?在Unix上,您可以使用std.socket创建Unix域套接字,类似于TCP套接字,但仅限于本地。下面是一些示例代码: // SERVER import std.socket; void main() { auto listener = new Sock

我正试图找出什么方法可以用于D中的IPC,主要是命名管道。我知道std.process包含来自相关进程的未命名管道的函数,尽管我更多地关注具有双向的不相关进程的ipc。我想我可能需要使用本地套接字,或者查看共享内存


有这样做的例子吗?

在Unix上,您可以使用std.socket创建Unix域套接字,类似于TCP套接字,但仅限于本地。下面是一些示例代码:

 // 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");
}
客户:

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();
}
他们唯一需要知道的是消息的含义(当然),以及到套接字的文件系统路径

Unix也有命名管道,但它们不像Unix域套接字(或Windows命名管道)那样是双向的

如果您确实需要一个unix命名管道,则它们称为FIFO文件,并使用mkfifo系统API函数生成。您可以通过
import core.sys.posix.sys.stat访问它然后使用与C中相同的方法:传递一个字符串和模式以创建文件,不要忘记检查返回值,然后使用常规Unix文件函数读取/写入它,例如,
读取
写入
关闭
,所有这些都来自
导入core.sys.posix.unistd。有关这些功能,请参阅C文档,例如
man2 read
man3 mkfifo
(如果您使用的是Linux),或者在web上搜索这些页面

但我认为unix域套接字是您所寻找的,它的工作原理与任何其他套接字基本相同,如上面的示例所示

Windows的做法有所不同,D标准库甚至不包括OS API函数原型

您可以使用该函数创建一个命名管道,并为其提供其他进程可以使用的路径名(类似于Unix域套接字,但不在统一文件系统中)。然后,使用CreateFile函数打开管道,然后,可以像其他文件一样与管道通信

有两种方法可以获取函数原型,以便您可以从D调用这些函数。一种是自己复制/粘贴它们,如下所示:

    extern(Windows)
    HANDLE CreateNamedPipeA(
            LPCTSTR lpName,
            DWORD dwOpenMode,
            DWORD dwPipeMode,
            DWORD nMaxInstances,
            DWORD nOutBufferSize,
            DWORD nInBufferSize,
            DWORD nDefaultTimeOut,
            LPSECURITY_ATTRIBUTES lpSecurityAttributes
    );
首先,
import core.sys.windows.windows
获取基本的Windows类型定义,然后将类似的内容添加到文件中。它与MSDN相同,只是删除了类似In的内容。(您也可以在
关键字中将它们更改为D的

最重要的是在名字上加上A或W。关于Unicode与ANSI名称的Microsoft文档底部提到了这一点。A版本采用ascii字符串。W版本采用D中的utf-16,
wstring
。建议使用W版本,但A版本在某些情况下更易于使用

或者,您可以从这里下载预先制作的win32绑定:并在构建时使用它们

如果您只需要几个函数,我更喜欢复制/粘贴以避免依赖关系,但是如果您正在进行大量Windows API工作,请下载完整的绑定

我用D编写了一个跨平台终端仿真器,它利用了以下技术:

可分离部分使用unix域套接字服务器:

可附加部分是UDS客户端

Windows emulator core使用一个专门的命名管道来执行我自己的异步“匿名”管道,而不是您的用例,但显示了如何调用函数:

共享内存是另一件您可以做的事情,但是您需要从D库获得很少的帮助,您将不得不使用OS函数。但这并不难,至少Unix上有函数原型:导入core.sys.posix.sys.shm并使用与C中相同的函数

我从来没有在Windows上做过,但快速搜索表明,您可以创建一个内存映射文件:

也许,只是也许会从火卫一那里得到帮助:但是,我从来没有真正尝试过这个。当我需要共享内存时,我只执行shmget等Unix函数(这是在我的simpledisplay.d中,它使用它与X服务器通信)

但底线是,Unix域套接字基本上与TCP套接字相同,而Phobos的std.socket可以提供帮助


其他所有操作都与C中的操作相同。

这些都是特定于操作系统的,因此我希望您必须使用C-api来创建它们。IPC问题的答案非常简单-您可以在系统上使用任何可用的IPC。D应用程序可以调用任何C库函数,记得吗?此外,如果你真的愿意,你可以直接从D进行系统调用…太好了,你的答案很有洞察力,还有你发布的代码示例。我计划买你的书和TDPL。我被D的强大而简单化所震惊。这对我来说是完美的语言。谢谢你的帮助。昨晚刚买了你的书,甚至还订了急件。我今天应该收到DCool。我在第41页简要介绍了unix套接字,这里有一个使用select()处理多个客户端的套接字服务器的示例,以及缓冲的工作原理(这些都可以在dlang.org网站文档中找到,但不是一个工作示例)。第四章也更详细地讨论了C和Windows函数的使用。(事实上,这本书的许多主题都是基于我以前在SO或D论坛上回答的问题!)