4
我已经命名了使用boost asio编写的管道服务器。服务器创建命名管道并调用ConnectNamedPipe,将asio重叠的ptr传递给它。问题是传递给asio的完成处理程序从不会被调用,即在客户端调用CreateFile将不会触发传递给ConnectNamedPipe的完成处理程序。我究竟做错了什么?ConnectNamedPipe和asio重叠ptr
这是客户端和服务器的完整清单:
#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对象 – iendgame 2014-12-08 19:07:12