Именованные каналы между C# и Python

Я пытаюсь создать двусторонний канал связи между двумя программами (одна на Python, а другая на С#)

Когда я создаю именованный канал между двумя программами C# или двумя программами Python, все в порядке, но когда я пытаюсь (например) подключиться к серверу C# из кода Python, это не работает:

Код С#:

NamedPipeServerStream server = new NamedPipeServerStream(
    "Demo", PipeDirection.InOut, 100, PipeTransmissionMode.Byte,
    PipeOptions.None, 4096, 4096)

Если я использую win32pipe в Python, блоки кода на ConnectNamedPipe (он никогда не возвращается)

p = win32pipe.CreateNamedPipe(
    r'\\.\pipe\Demo',
    win32pipe.PIPE_ACCESS_DUPLEX,
    win32pipe.PIPE_TYPE_BYTE | win32pipe.PIPE_WAIT,
    1, 65536, 65536,
    300,
    None)
win32pipe.ConnectNamedPipe(p)

Если я использую открытую функцию, она просто устанавливает соединение, но ничего не происходит:

open( '\\\\.\\pipe\\Demo', 'r+b' )

Теперь, если я закрою программу Python, сервер C# получит только один элемент данных от Python, а System.IO.IOException поднимется с сообщением «Канала сломана».

Я делаю что-то не так?


person Mehdi Asgari    schedule 17.11.2009    source источник


Ответы (3)


Согласно MS, ConnectNamedPipe является серверная функция для приема соединения. Вот почему он никогда не возвращается - он ждет подключения от клиента. Вот пример кода, показывающий C# в качестве сервера и python в качестве клиента:

С#:

using (var server = new NamedPipeServerStream("Demo"))
{
    server.WaitForConnection();

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

    server.Disconnect();
}

питон:

import win32file
fileHandle = win32file.CreateFile(
    "\\\\.\\pipe\\Demo", 
    win32file.GENERIC_READ | win32file.GENERIC_WRITE, 
    0, 
    None, 
    win32file.OPEN_EXISTING, 
    0, 
    None)
left, data = win32file.ReadFile(fileHandle, 4096)
print(data)  # "hello"
person Pakman    schedule 08.12.2010
comment
Это работает как шарм :) Спасибо, что сэкономили много моего времени, 8 лет спустя :) - person Alex; 20.09.2018

Хорошо, я исправил проблему. Я должен искать позицию 0 буфера.

Мой код Python:

    win32file.WriteFile(CLIENT_PIPE,"%d\r\n"%i ,None)
    win32file.FlushFileBuffers(CLIENT_PIPE)
    win32file.SetFilePointer(CLIENT_PIPE,0,win32file.FILE_BEGIN)
    i,s = win32file.ReadFile(CLIENT_PIPE,10,None)
person Mehdi Asgari    schedule 18.11.2009

Я думаю, вы должны использовать win32pipe.popen, а не open.

Также попробуйте: pipe.flush(), pipe.read() и time.sleep(0.01). Иногда для синхронизации IPC требуется некоторое время.

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

person wisty    schedule 17.11.2009
comment
Я использовал win32pipe.popen. Ничего не изменилось Удалось ли вам создать именованный канал между Python и .NET? Я не знаю, почему win32pipe.ConnectNamedPipe(p) никогда не возвращается - person Mehdi Asgari; 18.11.2009
comment
Я также использовал win32file, но теперь соединение устанавливается, но WriteFile не работает (да, я также сбрасывал буфер) - person Mehdi Asgari; 18.11.2009