ConnectNamedPipe 和 asio 重叠 ptr
Posted
技术标签:
【中文标题】ConnectNamedPipe 和 asio 重叠 ptr【英文标题】:ConnectNamedPipe and asio overlappped ptr 【发布时间】:2014-12-07 21:03:43 【问题描述】:我已经命名了使用 boost asio 编写的管道服务器。服务器创建命名管道并调用 ConnectNamedPipe,将 asio 重叠 ptr 传递给它。问题是传递给 asio 重叠的完成处理程序永远不会被调用,即在客户端调用 CreateFile 不会触发传递给 ConnectNamedPipe 的完成处理程序。我做错了什么?
这是客户端和服务器的完整列表:
#define _WIN32_WINNT 0x0501
#include <string>
#include <functional>
#include <thread>
#include <boost/system/error_code.hpp>
#include <boost/asio/io_service.hpp>
#include <boost/asio/windows/overlapped_ptr.hpp>
#include <boost/bind.hpp>
#include <tchar.h>
#include <Windows.h>
static const uint32_t PIPE_OUTPUT_BUFFER_RESERVED_SIZE_BYTES = 50 * 1024;
static const uint32_t PIPE_INPUT_BUFFER_RESERVED_SIZE_BYTES = 50 * 1024;
static const std::string PIPE_NAME = "\\\\.\\pipe\\BC33AFC8-BA51-4DCD-9507-0234785D4F55_native_server_pipe";
class Server
: public std::enable_shared_from_this<Server>
public:
Server()
~Server()
void Start()
mioservice = std::make_shared<boost::asio::io_service>();
mWork = std::make_shared<boost::asio::io_service::work>(*mIoService);
mThread = std::make_shared<std::thread>(
boost::bind(&boost::asio::io_service::run, mIoService));
mIoService->post(boost::bind(&Server::Accept, shared_from_this()));
void Accept()
mPipe = CreateNamedPipeA(
PIPE_NAME.c_str(),
PIPE_ACCESS_DUPLEX | FILE_FLAG_OVERLAPPED,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS,
PIPE_UNLIMITED_INSTANCES,
PIPE_OUTPUT_BUFFER_RESERVED_SIZE_BYTES,
PIPE_INPUT_BUFFER_RESERVED_SIZE_BYTES,
0,
nullptr);
if (mPipe == INVALID_HANDLE_VALUE)
DWORD err = GetLastError();
//LOG(Error, "Failed create pipe: " << mPipeName << ", error: " << err);
return;
//LOG(Trace, "Pipe: " << mPipeName << " created successfully");
boost::asio::windows::overlapped_ptr overlappedPtr(*mIoService,
std::bind(&Server::OnClientConnected, this, std::placeholders::_1, std::placeholders::_2));
OVERLAPPED* overlapped = overlappedPtr.get();
BOOL ok = ConnectNamedPipe(mPipe, overlapped);
DWORD lastError = GetLastError();
if (!ok && lastError != ERROR_IO_PENDING)
// The operation completed immediately, so a completion notification needs
// to be posted. When complete() is called, ownership of the OVERLAPPED-
// derived object passes to the io_service.
boost::system::error_code ec(lastError,
boost::asio::error::get_system_category());
overlappedPtr.complete(ec, 0);
else
// The operation was successfully initiated, so ownership of the
// OVERLAPPED-derived object has passed to the io_service.
overlappedPtr.release();
void OnClientConnected(
const boost::system::error_code& ec,
size_t bytesTransferred)
int a = 0;
a++;
private:
HANDLE mPipe;
std::shared_ptr<boost::asio::io_service> mIoService;
std::shared_ptr<boost::asio::io_service::work> mWork;
std::shared_ptr<std::thread> mThread;
;
class Client
public:
void Connect()
HANDLE hPipe = CreateFileA(
PIPE_NAME.c_str(),
GENERIC_READ | GENERIC_WRITE,
0,
nullptr,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
nullptr
);
if (hPipe == INVALID_HANDLE_VALUE)
DWORD err = GetLastError();
if (err != ERROR_PIPE_BUSY)
/*LOG(Error, "Failed create pipe: " << mPipeName << ", error: " << err);
mOnConnected(nullptr);*/
return;
return;
;
std::shared_ptr<Server> s = std::make_shared<Server>();
Client c;
int CALLBACK WinMain(
_In_ HINSTANCE hInstance,
_In_ HINSTANCE hPrevInstance,
_In_ LPSTR lpCmdLine,
_In_ int nCmdShow
)
s->Start();
Sleep(10000);
c.Connect();
Sleep(10000);
【问题讨论】:
在Server::Start方法的线程之前创建了io_service::work对象 【参考方案1】:发现问题。我没有在服务器部分将管道与IOCP
本身关联起来。这可以通过在调用ConnectNamedPipe
之前将CreateNamedPipeA
返回的管道原生句柄包装到boost::asio::windows::stream_handle
中来完成。
typedef boost::asio::windows::stream_handle StreamHandler;
std::shared_ptr<StreamHandler> streamHandler = std::make_shared<StreamHandler>(*mIoService);
streamHandle->assign(pipe);
【讨论】:
以上是关于ConnectNamedPipe 和 asio 重叠 ptr的主要内容,如果未能解决你的问题,请参考以下文章
BOOST_ASIO_ERROR_CATEGORY_NOEXCEPT 宏重定义