使用IOCP命名管道操作

时间:2013-06-23 16:53:42

标签: c++ windows pipe

我想使用命名管道实现异步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 ;

0 个答案:

没有答案