我想使用命名管道实现异步ipc类。我无法区分服务器进程和客户端进程,因为两个进程执行相同的工作并且可以随时打开。所以我先使用CreateFile
并根据返回值确定管道是否存在。一切似乎都很好,但我在ReadFile
上收到错误(GetLastError()
返回6,句柄无效)。这是我的代码:
DWORD max_pid = GetCurrentProcessId(), min_pid = pid;
MaxMin(max_pid, min_pid);
std::wstring pipe_name = PIPE_PREFIX +
I2WString(max_pid) + L"_" + I2WString(min_pid);
DWORD err;
connect_event_ = CreateEvent(NULL, TRUE, FALSE, NULL);
pipe_ = CreateFile(pipe_name.c_str(), GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (pipe_ == INVALID_HANDLE_VALUE) {
err = GetLastError();
if (err != ERROR_FILE_NOT_FOUND)
throw std::runtime_error("CreateFile failed. GetLastError == " +
I2String(err));
pipe_ = CreateNamedPipe(pipe_name.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED | FILE_FLAG_FIRST_PIPE_INSTANCE,
PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
1, MAX_BUFF_SIZE, MAX_BUFF_SIZE, 0, NULL);
if (pipe_ == INVALID_HANDLE_VALUE)
throw std::runtime_error("CreateNamedPipe failed. GetLastError == " +
I2String(GetLastError()));
Request *req = RequestsPool::Get();
req->hEvent = connect_event_;
BOOL conn_f = ConnectNamedPipe(pipe_, req);
if (!conn_f) {
err = GetLastError();
if (err != ERROR_IO_PENDING && err != ERROR_PIPE_CONNECTED)
throw std::runtime_error("ConnectNamedPipe failed. GetLastError == " +
I2String(err));
}
} else {
DWORD mode = PIPE_READMODE_MESSAGE;
if (!SetNamedPipeHandleState(pipe_, &mode, NULL, NULL))
throw std::runtime_error("SetNamedPipeHandleState failed. GetLastError == " +
I2String(GetLastError()));
SetEvent(connect_event_);
}
if ((completion_port_ = CreateIoCompletionPort(pipe_, NULL, 0, 0)) == NULL)
throw std::runtime_error("CreateIoCompletionPort failed. GetLastError == " +
I2String(GetLastError()));
if (WaitForSingleObject(connect_event_, INFINITE) != WAIT_OBJECT_0)
throw std::runtime_error("WaitForSingleObject failed. GetLastError == " +
I2String(GetLastError()));
Request *req = RequestsPool::Get();
if (ReadFile(pipe_, req->read_buff, MAX_BUFF_SIZE, NULL, req) == FALSE)
if ((err = GetLastError()) != ERROR_IO_PENDING)
DLOG(FATAL) << "ReadFile failed. GetLastError == " << err;
// create a thread to handle the IO results
CreateThread(NULL, 0, DispatchThread_, this, NULL, NULL);
return ;