【问题标题】:How to do IPC using Unix Domain Socket in D?如何在 D 中使用 Unix Domain Socket 进行 IPC?
【发布时间】:2020-08-19 03:40:35
【问题描述】:

这里我有一个程序想要

  1. 检测是否是唯一的实例

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

  2. 如果没有运行重复的程序,则建立 UDS 然后监听套接字。

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

    2.2。否则它应该一直监听套接字

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

这是我所拥有的:

import std.socket, std.experimental.logger;

immutable string socketAddress = "\0/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.");
    }
}

对于那些没有任何套接字编程经验的人来说,该文档似乎不太友好。如何使用 std.socket.Socket 发送和接收消息?

【问题讨论】:

  • 我不知道你的代码有什么问题,但我最近写了一个例子,你可能会觉得有用Protocol Buffers and BSD Sockets。插座部分基于 Adam D. Ruppe 的书;)希望对您有所帮助!

标签: d unix-socket


【解决方案1】:

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

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

它是 tcp,但让它成为 unix 只是意味着改变家族,就像你已经在你的代码中所做的那样。

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

【讨论】:

  • 由于Unable to accept socket connection: Invalid argument,应用accept() 方法并使用返回的套接字结果到SocketAcceptException。来源:run.dlang.io/is/2vXzIf
  • 你给了它一个空缓冲区。试试char[1024] buffer; receive(buffer[])。注意接收返回实际使用了多少缓冲区。
  • 问题仍然存在“无法接受套接字连接:无效参数”run.dlang.io/is/jcUvU4
  • 啊,再看看我错过了更多:你需要listen oyu 才能接受。侦听由第一个套接字完成,而不是接收器套接字。在它收听之后(顺便说一句,使用非零参数来收听),那么你可以接受。这些事情的顺序很重要,请参阅我的示例代码以查看工作示例
  • 谢谢,成功了。但是,为什么 listen(int backlog) 的论点不适合 0 呢?文档说backlog 是一个请求,即有多少待处理的传入连接排队等待被接受。这是否意味着每两条传入消息都会监听该消息?
【解决方案2】:

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

import std.socket, std.experimental.logger;

class UDSIPC
{
private:
    static immutable string socketAddress = "\0/tmp/com.localserver.myapp";
    static immutable size_t messageBufferSize = 64;
    static immutable string socketAddressName = "\0/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());
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 2016-08-28
    • 2019-07-02
    • 1970-01-01
    • 2012-10-13
    • 1970-01-01
    相关资源
    最近更新 更多