How to do IPC using Unix Domain Socket?

Hossain Adnan relay.public.adnan at outlook.com
Thu Oct 10 17:10:06 UTC 2019


On Thursday, 10 October 2019 at 12:30:25 UTC, Hossain Adnan wrote:
> Here I have a program that wants to
>
> 1. detect whether if it's the only instance
>     1.1. it does that by trying to create a Unix Domain Socket
>     and trying to binding it to a specific address.
>
> 2. if a duplicate program is not running, establish an UDS
>     and then listen to the socket.
>
>     2.1. if any message comes through that socket, the program 
> will log the incoming message
>     2.2. otherwise it should keep listening to the socket 
> forever
>
> 3. if there's a duplicate program it should send a message and 
> then exit.
>
> Here's what I 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.");
> 	}
> }
>
>
> The documentation does not seem very friendly to those who does 
> not have any experience in socket programming.

Consulted stackoverflow and came up with this:

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());
	}
}



More information about the Digitalmars-d-learn mailing list