C#和Python之间的命名管道

8

我正在尝试创建两个程序之间的双向通信渠道(一个是Python程序,另一个是C#程序)。

当我在两个C#程序或两个Python程序之间创建命名管道时,一切正常,但是当我尝试从Python代码连接到C#服务器时,它无法工作:

C#代码:

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

如果我在Python中使用win32pipe,代码会在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函数,它只是建立了一个连接,但没有任何操作发生:

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

现在,如果我关闭Python程序,C#服务器只会从Python接收到一个数据项,并且会出现“管道已中断”的错误信息System.IO.IOException

我做错了什么吗?


这个问题帮助我写了这篇博客文章 - Jonathon Reinhart
3个回答

11
根据微软,ConnectNamedPipe是"接受连接的服务器端函数"。这就是为什么它从不返回 - 它正在等待客户端的连接。以下是一些示例代码,显示C#作为服务器,Python作为客户端:

C#:

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

Python:

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"

5
太棒了,这个方法很有效!感谢你在8年后节省了我很多时间 :) - Alex
确实,这是一个非常简单且有效的例子!我只想补充一点小事情,这也让我花费了一些时间。在这个例子中,两个进程需要以相同的提升权限运行,否则你会得到ERROR_ACCESS_DENIED错误。 - Tycho

1

好的,问题已经解决。我应该寻找缓冲区的位置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)

0

我认为你应该使用win32pipe.popen而不是open。

另外尝试一下:pipe.flush(),pipe.read()和time.sleep(0.01)。有时IPC需要一段时间才能同步。

我不太确定,这是我使用子进程管道的经验。win32pipe可能会有所不同。


我使用了win32pipe.popen。但是什么也没有改变。 你是否成功在Python和.NET之间创建了一个命名管道? 我不知道为什么win32pipe.ConnectNamedPipe(p)从未返回。 - Mehdi Asgari
我之前也使用了win32file,但现在连接已经建立,但WriteFile不起作用(是的,我也刷新了缓冲区)。 - Mehdi Asgari

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接