如何在 D 中使用 Unix 域套接字进行 IPC?

How to do IPC using Unix Domain Socket in D?

这里我有一个程序想要

  1. 检测是否是唯一实例

    1.1。它通过尝试创建一个 Unix Domain Socket 来做到这一点 并尝试将其绑定到特定地址。

  2. 如果重复程序不是运行,建立一个UDS 然后听套接字。

    2.1。如果有任何消息通过该套接字,程序将记录传入的消息

    2.2。否则它应该永远监听套接字

  3. 如果有重复的程序,它应该发送一条消息然后退出。

这是我拥有的:

import std.socket, std.experimental.logger;

immutable string socketAddress = "[=10=]/tmp/com.localserver.myapp";

void main()
{
    auto socket = new std.socket.Socket(std.socket.AddressFamily.UNIX,
            std.socket.SocketType.STREAM);
    auto addr = new std.socket.UnixAddress(socketAddress);

    auto isUnique = () {
        bool result;

        scope (success)
            log("returns: ", result);

        try
        {
            socket.bind(addr);
            result = true;
        }
        catch (std.socket.SocketOSException e)
            result = false;

        // else throw error
        return result;
    }();

    if (isUnique)
    {
        log("Unique instance detected. Listening...");
        // works upto now
        char[] buffer = [];
        while (1)
        {
            socket.listen(0);
            socket.receive(buffer);
            if (buffer != []) {
                log("Received message: ", buffer);
            }
            buffer = [];
        }
    }
    else
    {
        log("Duplicate instance detected.");
        socket.connect(addr);
        import std.stdio;
        stdout.write("Enter your message:\t");
        socket.send(readln());
        log("Message has been sent. Exiting.");
    }
}

文档对于没有socket编程经验的人来说似乎不是很友好。如何使用 std.socket.Socket 发送和接收消息?

绑定后,其实还需要accept。它将 return 一个新的 Socket 实例,您实际上可以从中 receive 。您的客户端分支看起来不错。我认为这是你的主要错误。

我的书中也有一个代码示例,它显示了 std.socket 的基本功能,可以作为示例提供帮助: http://arsdnet.net/dcode/book/chapter_02/03/

它是 tcp,但使其成为 unix 就意味着改变系列,就像您在代码中所做的那样。

您还可以查找 C 等的套接字教程,D 套接字只是那些相同 BSD 风格套接字函数的薄包装。

正如 Adam 指出的那样,我首先使用了 listen() 方法,然后应用 accept() 方法,其中 returns 一个可以接收消息的套接字。然后接收器套接字占用 char[N] 缓冲区。

import std.socket, std.experimental.logger;

class UDSIPC
{
private:
    static immutable string socketAddress = "[=10=]/tmp/com.localserver.myapp";
    static immutable size_t messageBufferSize = 64;
    static immutable string socketAddressName = "[=10=]/tmp/com.localserver.myapp";
    Socket socket;
    UnixAddress uaddr;

public:
    this(in string socketAddressName = socketAddressName)
    {
        socket = new Socket(AddressFamily.UNIX, SocketType.STREAM);
        uaddr = new UnixAddress(socketAddress);
    }

    bool getUniqueness()
    {
        bool result;

        scope (success)
            log("returns: ", result);

        try
        {
            socket.bind(uaddr);
            result = true;
        }
        catch (SocketOSException e)
            result = false;

        // else throw error
        return result;
    }

    string getMessage()
    {
        socket.listen(0);
        auto receiverSocket = socket.accept();
        char[messageBufferSize] buffer;
        auto amount = receiverSocket.receive(buffer);
        import std.string;
        return format!"%s"(buffer[0 .. amount]);
    }

    void sendMessage(in string message)
    {
        socket.connect(uaddr);
        socket.send(message);
    }

}

void main()
{
    auto ipc = new UDSIPC();

    if (ipc.getUniqueness())
    {
        while (true)
        {
            log(ipc.getMessage());
        }
    }
    else
    {
        import std.stdio, std.string;
        ipc.sendMessage(readln().chomp());
    }
}