在断开连接之前等待命名管道被读取
Wait for Named Pipe to be read before Disconnecting
我有一个用 Python 编写的程序,我需要从 C++ 程序中联系它。我在 C++ 程序上创建管道服务器,客户端位于 Python。每次我尝试不同的行为时,我都不知道如何在这两个程序之间正确 read/write 。请注意,我希望管道在未来的多个 reads/writes 中保持打开状态。
服务器 (C++)
#include <windows.h>
#include <iostream>
using namespace std;
#define FGPIPE TEXT("\\.\pipe\FGChroma")
int main()
{
HANDLE hPipe;
DWORD dwWritten;
DWORD MAX_BUF_SIZE = 8;
hPipe = CreateNamedPipe(FGPIPE,
PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
2,
MAX_BUF_SIZE*16,
0,
NMPWAIT_USE_DEFAULT_WAIT,
NULL
);
cout<<"Pipe? "<<hPipe<<endl;
cout<<"Awaiting Connection"<<endl;
cout<<ConnectNamedPipe(hPipe, NULL)<<endl;
cout<<"Connected"<<endl;
WriteFile(hPipe, "MSG1\n", 5, &dwWritten, NULL);
WriteFile(hPipe, "MSG2\n", 5, &dwWritten, NULL);
FlushFileBuffers(hPipe);
///Need to Wait for read here
cout<<"Disconnecting"<<endl;
DisconnectNamedPipe(hPipe);
}
客户(Python)
f = open(r"\.\pipe\FGChroma", 'r', 0)
while True:
value = f.read()
print(value)
当我尝试在 Python 中执行 f.read()
时,我收到错误 OSError 22 Invalid Argument,这是公平的,因为我已经断开了管道。但是,如果我不断开管道,那么 Python 代码永远不会完成读取并一直等待,直到管道关闭或断开连接。我觉得解决方案很简单,我只是遗漏了一些让我头疼的小事。我阅读了命名管道和 Win API 的文档,我也尝试了 win32py 和其他替代方案,但我遇到了同样的问题;我不明白如何在 2 个实例之间保持连接并允许读取而无需断开连接或等待读取。
你可以在这里看看Python and Windows Named Pipes
认为 windows 由多个程序打开一个文件不像在 unix 上那样。如果你无法避免它使用 win32pipe 但这会使你的代码不是平台独立的
我认为 Python f.read()
和 Windows 管道有问题。也许我错过了一些东西,但是当你像你一样阅读管道时看起来没有 EOF,并且 python read()
会读到结尾和错误,即使它之前正确地读取了所有内容。
要解决此问题,您可以使用缓冲管道 (open(r"pipe", 'r')
),然后一个一个地读取字符 (f.read(1)
) 直到出现错误,或者使用 os.read(f.fileno(), 1024)
,这是较低的级别,在这种情况下有效。
根据上面 ElderBug 的回答,这里有一个不使用缓冲区但使用行尾终止符的可行解决方案。您可能需要相应地调整您的代码。
def read_line(file_handle):
EOF = False
data = ""
while True:
try:
c = file_handle.read(1).decode("utf-8")
except OSError: # EOF
EOF = True
break
if c == '\n':
break
if not c:
EOF = True
break
data += c
return data, EOF
print("Connecting to Pipe")
while True:
try:
f = open(r"\.\pipe\FGChroma", 'rb', 0)
break
except FileNotFoundError:
continue
print("Connected")
print("Reading Data")
while True:
data, EOF = read_line(f)
if EOF: break
print(data)
您可能还需要将阅读模式从 'rb'
切换到 'r'
。仅对二进制模式使用 b
,但是您必须通过将缓冲模式从 0
.
设置为 1
来启用缓冲
我有一个用 Python 编写的程序,我需要从 C++ 程序中联系它。我在 C++ 程序上创建管道服务器,客户端位于 Python。每次我尝试不同的行为时,我都不知道如何在这两个程序之间正确 read/write 。请注意,我希望管道在未来的多个 reads/writes 中保持打开状态。
服务器 (C++)
#include <windows.h>
#include <iostream>
using namespace std;
#define FGPIPE TEXT("\\.\pipe\FGChroma")
int main()
{
HANDLE hPipe;
DWORD dwWritten;
DWORD MAX_BUF_SIZE = 8;
hPipe = CreateNamedPipe(FGPIPE,
PIPE_ACCESS_OUTBOUND,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT,
2,
MAX_BUF_SIZE*16,
0,
NMPWAIT_USE_DEFAULT_WAIT,
NULL
);
cout<<"Pipe? "<<hPipe<<endl;
cout<<"Awaiting Connection"<<endl;
cout<<ConnectNamedPipe(hPipe, NULL)<<endl;
cout<<"Connected"<<endl;
WriteFile(hPipe, "MSG1\n", 5, &dwWritten, NULL);
WriteFile(hPipe, "MSG2\n", 5, &dwWritten, NULL);
FlushFileBuffers(hPipe);
///Need to Wait for read here
cout<<"Disconnecting"<<endl;
DisconnectNamedPipe(hPipe);
}
客户(Python)
f = open(r"\.\pipe\FGChroma", 'r', 0)
while True:
value = f.read()
print(value)
当我尝试在 Python 中执行 f.read()
时,我收到错误 OSError 22 Invalid Argument,这是公平的,因为我已经断开了管道。但是,如果我不断开管道,那么 Python 代码永远不会完成读取并一直等待,直到管道关闭或断开连接。我觉得解决方案很简单,我只是遗漏了一些让我头疼的小事。我阅读了命名管道和 Win API 的文档,我也尝试了 win32py 和其他替代方案,但我遇到了同样的问题;我不明白如何在 2 个实例之间保持连接并允许读取而无需断开连接或等待读取。
你可以在这里看看Python and Windows Named Pipes
认为 windows 由多个程序打开一个文件不像在 unix 上那样。如果你无法避免它使用 win32pipe 但这会使你的代码不是平台独立的
我认为 Python f.read()
和 Windows 管道有问题。也许我错过了一些东西,但是当你像你一样阅读管道时看起来没有 EOF,并且 python read()
会读到结尾和错误,即使它之前正确地读取了所有内容。
要解决此问题,您可以使用缓冲管道 (open(r"pipe", 'r')
),然后一个一个地读取字符 (f.read(1)
) 直到出现错误,或者使用 os.read(f.fileno(), 1024)
,这是较低的级别,在这种情况下有效。
根据上面 ElderBug 的回答,这里有一个不使用缓冲区但使用行尾终止符的可行解决方案。您可能需要相应地调整您的代码。
def read_line(file_handle):
EOF = False
data = ""
while True:
try:
c = file_handle.read(1).decode("utf-8")
except OSError: # EOF
EOF = True
break
if c == '\n':
break
if not c:
EOF = True
break
data += c
return data, EOF
print("Connecting to Pipe")
while True:
try:
f = open(r"\.\pipe\FGChroma", 'rb', 0)
break
except FileNotFoundError:
continue
print("Connected")
print("Reading Data")
while True:
data, EOF = read_line(f)
if EOF: break
print(data)
您可能还需要将阅读模式从 'rb'
切换到 'r'
。仅对二进制模式使用 b
,但是您必须通过将缓冲模式从 0
.
1
来启用缓冲