Overlapped Pipe
-
Hi!
Ich hab ein Problem mit Named Pipes im Overlapped-Modus. Mein Pipe-Server arbeitet beim ersten Durchlauf (Client verbindet sich, sendet Daten und Client trennt sich wieder) richtig. Wenn ich anschließend aber mich wieder verbinde, scheitert ReadFileEx() mit dem Fehler ERROR_PIPE_LISTENING. Woran kann das liegen?
struct context_type { OVERLAPPED overlapped; HANDLE pipe; std::vector<std::uint8_t> buffer; context_type() { std::memset(&overlapped, 0, sizeof overlapped); } }; ... void pipe_end::listen() { listen_thread_.swap(std::thread([=]() { OVERLAPPED overlapped = { 0 }; overlapped.hEvent = event_; try { for (;;) { HANDLE pipe = CreateNamedPipe(L"\\\\.\\pipe\\neoee", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_ACCEPT_REMOTE_CLIENTS, PIPE_UNLIMITED_INSTANCES, buffer_size_, buffer_size_, 0, 0); if (pipe == 0 || pipe == INVALID_HANDLE_VALUE) throw std::runtime_error("could not initialize named control pipe"); if (ConnectNamedPipe(pipe, &overlapped) == 0) { switch (GetLastError()) { case ERROR_IO_PENDING: { auto result = WaitForSingleObjectEx(overlapped.hEvent, INFINITE, TRUE); if (result == FAIT_FAILED) throw std::runtime_error("pipe waiting mode failure"); else if (result == WAIT_IO_COMPLETION) break; if (signaled_) return; } case ERROR_PIPE_CONNECTED: { context_type* context = new context_type; context->pipe = pipe; context->buffer.resize(buffer_size_); // SCHEITERT BEIM ZWEITEN MAL! if (ReadFileEx(context->pipe, &context->buffer[0], static_cast<DWORD>(context->buffer.size()), reinterpret_cast<OVERLAPPED*>(&context->overlapped), &pipe_end::completion_routine) == FALSE) { delete context; DisconnectNamedPipe(context->pipe); CloseHandle(context->pipe); throw std::runtime_error("reading pipe error"); } } break; default: CloseHandle(pipe); throw std::runtime_error("pipe connection failure"); } } else { throw std::runtime_error("ConnectNamedPipe failure"); } } } catch (const std::runtime_error& error) { std::cerr << "Pipe exception: " << error.what() << std::endl; } })); } void WINAPI pipe_end::completion_routine(DWORD error, DWORD transferred, OVERLAPPED* overlapped) { std::unique_ptr<context_type> context(CONTAINING_RECORD(overlapped, context_type, overlapped)); if (error) throw std::runtime_error("read pipe completion failure"); std::cout << transferred << std::endl; DisconnectNamedPipe(context->pipe); CloseHandle(context->pipe); }
-
Dass beim Error-Handling das delete zu früh kommt weiß ich, aber das war auch nicht die Ursache.
-
Lies dir einfach mal die MSDN-Beschreibung zu ConnectNamedPipe() durch.
Ganz unten wird dein Problem beschrieben!