Двунаправленная связь между Python и C#

#python #c# #ipc #named-pipes

Вопрос:

Я работаю над проектом, в котором мне нужно довольно гибко соединять Python и C#, при этом информация часто передается от одного к другому. Большую часть времени данные передаются туда и обратно (A работает с данными, отправляет результат B, B работает с результатом, отвечает A), но не всегда это необходимо.

Именованные каналы казались подходящим решением, но я изо всех сил стараюсь, чтобы все это было синхронно.

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

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

Являются ли именованные каналы слишком упрощенными для такой задачи, или есть способ сделать эту работу надежной?

Обновление: Для справки, как выглядит мой код (здесь сведено к минимуму):

Сначала сервер и клиент NamedPipe в C#

 public static void SendDataToPython(string payload)
{
    using (var server = new NamedPipeServerStream("Test"))
    {
        server.WaitForConnection();

        using (var stream = new MemoryStream())
        using (var writer = new BinaryWriter(stream))
        {
            writer.Write(payload);
            server.Write(stream.ToArray(), 0, stream.ToArray().Length);
        }

        server.Disconnect();
    }
}



public static string WaitForMessage()
{
    string message = "";
    string servername = ".";
    string pipeName = "CSServer";
    using (var pipeClient = new NamedPipeClientStream(servername, pipeName, PipeDirection.In))
    {
        pipeClient.Connect();
 

И в Python:

 class PipeServer():
    def __init__(self, pipeName):
        self.pipe = win32pipe.CreateNamedPipe(
            r'\.pipe\'   pipeName,
            win32pipe.PIPE_ACCESS_DUPLEX,
            win32pipe.PIPE_TYPE_MESSAGE | win32pipe.PIPE_READMODE_MESSAGE | win32pipe.PIPE_WAIT,
            1, 65536, 65536,
            0,
            None)

    def connect(self):
        win32pipe.ConnectNamedPipe(self.pipe, None)

    def write(self, message):
        win32file.WriteFile(self.pipe, message.encode()   b'n')

    def close(self):
        win32file.CloseHandle(self.pipe)

            using (StreamReader sr = new StreamReader(pipeClient))
            {
                string temp;
                while ((temp = sr.ReadLine()) != null)
                {
                    message  = temp;
                }
            }
        }
        return message;
    }

class PipeClient:
    def __init__(self, pipeName):
        self.pipeName = pipeName

    def receive(self):
        file_handle = win32file.CreateFile(
            f"\\.\pipe\{self.pipeName}",
            win32file.GENERIC_READ | win32file.GENERIC_WRITE,
            0,
            None,
            win32file.OPEN_EXISTING,
            0,
            None)
        left, data = win32file.ReadFile(file_handle, 4096)
        print(data.decode("utf-8")[1:])
 

Комментарии:

1. Как «Создать сервер»? TCP-сокеты? Может быть, посмотрите на ZeroMQ или gRPC, если не простой RESTful JSON API по HTTP

2. В конечном итоге «gRPC» может помочь вам

3. @OneCricketeer «Создает сервер» с использованием именованных каналов, как уже упоминалось. В C# с метким именем NamedPipeServerStream. Возможно, «Создание» — неподходящее слово, извините, если это так.

4. Я не знаком с C#, поэтому мне непонятно, как Python узнает «имя именованного канала», чтобы подключиться к нему (у вас уже есть код, которым вы можете поделиться?). В противном случае, похоже, вам нужно решение, не зависящее от языка, такое как упомянутые

5. Код теперь включен. Клиент и сервер распознают друг друга по одному и тому же имени (на локальном компьютере). Предлагаемые решения, безусловно, выглядят хорошо, но сначала мне придется в них разобраться.