1

Title sums it up. There are plenty of examples around with a c# server and python client communicating back and forth.

I'd like to understand how I can instead create a python server and c# client for some interprocess communication.

SockPastaRock
  • 301
  • 3
  • 13
  • If you have examples for the other way around, can't you just translate the code? – Grim Jul 16 '19 at 11:57
  • Take anything that sets up a named pipe server in Python (for example from [this question](https://stackoverflow.com/q/48542644/4137916)) and start from there. Finding client code for C# won't be the problem. – Jeroen Mostert Jul 16 '19 at 12:04

1 Answers1

3

I managed to find a solution. To begin, I'd first like to clarify some confusing terminology and obscure naming conventions used in dotnet core.

It appears that the NamedPipeServerStream and NamedPipeClientStream don't actually operate on named pipes but instead on unix domain sockets. This means that we must use sockets to communicate between processes rather than FIFO files.

Another frustration I find with dotnet core is that when creating a socket or connecting to one, the NamedPipeServerStream and NamedPipeClientStream classes will add "CoreFxPipe_" to the beginning of the socket name. See related question.

Python Server

#!/usr/bin/python3

import socket
import os
import struct

SOCK_PATH = "/tmp/CoreFxPipe_mySocket"

with socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) as sock:
    try:
        os.remove(SOCK_PATH)
    except OSError:
        pass
    sock.bind(SOCK_PATH)
    sock.listen()
    conn, addr = sock.accept()
    with conn:
        try:
            while True:
                amount_expected = struct.unpack('I', conn.recv(4))[0]
                print("amount_expected :", amount_expected)

                message = conn.recv(amount_expected)
                print("Received message : ", message.decode())

                # Send data
                message_rev = message[::-1].decode()
                print("Sent message (reversed) : ", message_rev)

                conn.sendall(
                    struct.pack(
                        'I',
                        len(message_rev)
                    )
                    + message_rev.encode('utf-8')
                )

        except (struct.error, KeyboardInterrupt) as e:
            print(e)

        finally:
            print('closing socket')

C# Client

using System;
using System.IO;
using System.IO.Pipes;
using System.Text;

class PipeClient
{
    static void Main(string[] args)
    {
        using (NamedPipeClientStream pipeClient =
            new NamedPipeClientStream(".", "mySocket", PipeDirection.InOut))
        {

            // Connect to the pipe or wait until the pipe is available.
            Console.WriteLine("Attempting to connect to pipe...");
            pipeClient.Connect();

            try
            {
                // Read user input and send that to the client process.
                using (BinaryWriter _bw = new BinaryWriter(pipeClient))
                using (BinaryReader _br = new BinaryReader(pipeClient))
                {
                    while (true)
                    {
                        //sw.AutoFlush = true;
                        Console.Write("Enter text: ");
                        var str = Console.ReadLine();

                        var buf = Encoding.ASCII.GetBytes(str);     // Get ASCII byte array
                        _bw.Write((uint)buf.Length);                // Write string length
                        _bw.Write(buf);                              // Write string
                        Console.WriteLine("Wrote: \"{0}\"", str);
                        Console.WriteLine("Let's hear from the server now..");

                        var len = _br.ReadUInt32();
                        var temp = new string(_br.ReadChars((int)len));

                        Console.WriteLine("Received from client: {0}", temp);
                    }
                }
            }
            // Catch the IOException that is raised if the pipe is broken
            // or disconnected.
            catch (IOException e)
            {
                Console.WriteLine("ERROR: {0}", e.Message);
            }

        }
        Console.Write("Press Enter to continue...");
    }
}

Sources:

https://abgoswam.wordpress.com/2017/07/13/named-pipes-c-python-net-core/

https://realpython.com/python-sockets/

https://unix.stackexchange.com/questions/75904/are-fifo-pipe-unix-domain-socket-the-same-thing-in-linux-kernel

SockPastaRock
  • 301
  • 3
  • 13