Как сделать IPC используя Unix Domain Socket в D? - PullRequest
2 голосов
/ 10 октября 2019

Здесь у меня есть программа, которая хочет

  1. определить, является ли это единственный экземпляр

    1.1. он делает это, пытаясь создать Unix Domain Socket и пытаясь привязать его к определенному адресу.

  2. , если дублирующая программа не запущена, установить UDS и затем прослушать сокет.

    2.1. если какое-либо сообщение поступает через этот сокет, программа зарегистрирует входящее сообщение

    2.2. в противном случае он должен постоянно слушать сокет

  3. , если есть дублирующаяся программа, она должна отправить сообщение и затем выйти.

Вот что яhave:

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?

Ответы [ 2 ]

3 голосов
/ 10 октября 2019

После связывания вам действительно нужно accept. Он вернет новый экземпляр Socket, с которого вы можете receive. Ваша ветка на стороне клиента выглядит нормально. Я думаю, что это ваша ключевая ошибка здесь.

У меня также есть пример кода в моей книге, который показывает основные функции std.socket, который может помочь в качестве примера: http://arsdnet.net/dcode/book/chapter_02/03/

этоtcp, но сделать его Unix просто означает изменение семейства, как вы уже сделали в своем коде.

Вы также можете посмотреть учебные пособия по сокетам для C и так далее, D-сокет - просто тонкая оболочка для тех же самыхФункции сокетов в стиле BSD.

0 голосов
/ 10 октября 2019

Как указал Адам, я сначала использовал метод 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());
    }
}
...