C#与Python之间的命名管道

8 投票
3 回答
16402 浏览
提问于 2025-04-15 16:06

我正在尝试在两个程序之间建立一个双向通信的通道,一个是用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的错误,提示“管道已损坏”。

我是不是做错了什么?

3 个回答

0

我觉得你应该用win32pipe.popen,而不是open。

你也可以试试:pipe.flush()、pipe.read(),还有time.sleep(0.01)。有时候进程间通信需要一点时间来同步。

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

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"
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)

撰写回答