C++ Boost::Asio::Ip::Tcp::Iostream问题
嘿,我是asio和boost的新手,我一直在尝试实现一个TCP服务器和客户机,这样我就可以传输一个std::vector,但到目前为止我失败了。我发现Asio的boost文档缺乏(至少可以说)而且很难理解(英语不是我的主要语言) 无论如何,我一直在看iostreams的例子,我一直在尝试实现一个面向对象的解决方案,但我失败了 我试图实现的服务器应该能够接受来自多个客户机的连接(我该怎么做?) 服务器应该接收std::vector,/*执行某些操作*/然后将其返回给客户机,以便客户机可以判断服务器接收到的数据是完整的 *.h文件C++ Boost::Asio::Ip::Tcp::Iostream问题,c++,boost-asio,C++,Boost Asio,嘿,我是asio和boost的新手,我一直在尝试实现一个TCP服务器和客户机,这样我就可以传输一个std::vector,但到目前为止我失败了。我发现Asio的boost文档缺乏(至少可以说)而且很难理解(英语不是我的主要语言) 无论如何,我一直在看iostreams的例子,我一直在尝试实现一个面向对象的解决方案,但我失败了 我试图实现的服务器应该能够接受来自多个客户机的连接(我该怎么做?) 服务器应该接收std::vector,/*执行某些操作*/然后将其返回给客户机,以便客户机可以判断服务器
class TCP_Server : private boost::noncopyable
{
typedef boost::shared_ptr<TCP_Connection> tcp_conn_pointer;
public :
TCP_Server(ba::io_service &io_service, int port);
virtual ~TCP_Server() {}
virtual void Start_Accept();
private:
virtual void Handle_Accept(const boost::system::error_code& e);
private :
int m_port;
ba::io_service& m_io_service; // IO Service
bi::tcp::acceptor m_acceptor; // TCP Connections acceptor
tcp_conn_pointer m_new_tcp_connection; // New connection pointer
};
TCP_Server::TCP_Server(boost::asio::io_service &io_service, int port) :
m_io_service(io_service),
m_acceptor(io_service, bi::tcp::endpoint(bi::tcp::v4(), port)),
m_new_tcp_connection(TCP_Connection::Create(io_service))
{
m_port = port;
Start_Accept();
}
void TCP_Server::Start_Accept()
{
std::cout << "[TCP_Server][Start_Accept] => Listening on port : " << m_port << std::endl;
//m_acceptor.async_accept(m_new_tcp_connection->Socket(),
// boost::bind(&TCP_Server::Handle_Accept, this,
// ba::placeholders::error));
m_acceptor.async_accept(*m_stream.rdbuf(),
boost::bind(&TCP_Server::Handle_Accept,
this,
ba::placeholders::error));
}
void TCP_Server::Handle_Accept(const boost::system::error_code &e)
{
if(!e)
{
/*boost::thread T(boost::bind(&TCP_Connection::Run, m_new_tcp_connection));
std::cout << "[TCP_Server][Handle_Accept] => Accepting incoming connection. Launching Thread " << std::endl;
m_new_tcp_connection = TCP_Connection::Create(m_io_service);
m_acceptor.async_accept(m_new_tcp_connection->Socket(),
boost::bind(&TCP_Server::Handle_Accept,
this,
ba::placeholders::error));*/
m_stream << "Server Response..." << std::endl;
}
}
类TCP_服务器:私有boost::不可复制
{
typedef boost::共享的\u ptr tcp\u连接\u指针;
公众:
TCP_服务器(ba::io_服务和io_服务,int端口);
虚拟~TCP_服务器(){}
虚拟无效开始_接受();
私人:
虚拟无效句柄(const boost::system::error\u code&e);
私人:
国际港口;
ba::io_服务&m_io_服务;//io服务
bi::tcp::acceptor m_acceptor;//tcp连接acceptor
tcp\u连接\u指针m\u新建\u tcp\u连接;//新建连接指针
};
*.cpp文件
class TCP_Server : private boost::noncopyable
{
typedef boost::shared_ptr<TCP_Connection> tcp_conn_pointer;
public :
TCP_Server(ba::io_service &io_service, int port);
virtual ~TCP_Server() {}
virtual void Start_Accept();
private:
virtual void Handle_Accept(const boost::system::error_code& e);
private :
int m_port;
ba::io_service& m_io_service; // IO Service
bi::tcp::acceptor m_acceptor; // TCP Connections acceptor
tcp_conn_pointer m_new_tcp_connection; // New connection pointer
};
TCP_Server::TCP_Server(boost::asio::io_service &io_service, int port) :
m_io_service(io_service),
m_acceptor(io_service, bi::tcp::endpoint(bi::tcp::v4(), port)),
m_new_tcp_connection(TCP_Connection::Create(io_service))
{
m_port = port;
Start_Accept();
}
void TCP_Server::Start_Accept()
{
std::cout << "[TCP_Server][Start_Accept] => Listening on port : " << m_port << std::endl;
//m_acceptor.async_accept(m_new_tcp_connection->Socket(),
// boost::bind(&TCP_Server::Handle_Accept, this,
// ba::placeholders::error));
m_acceptor.async_accept(*m_stream.rdbuf(),
boost::bind(&TCP_Server::Handle_Accept,
this,
ba::placeholders::error));
}
void TCP_Server::Handle_Accept(const boost::system::error_code &e)
{
if(!e)
{
/*boost::thread T(boost::bind(&TCP_Connection::Run, m_new_tcp_connection));
std::cout << "[TCP_Server][Handle_Accept] => Accepting incoming connection. Launching Thread " << std::endl;
m_new_tcp_connection = TCP_Connection::Create(m_io_service);
m_acceptor.async_accept(m_new_tcp_connection->Socket(),
boost::bind(&TCP_Server::Handle_Accept,
this,
ba::placeholders::error));*/
m_stream << "Server Response..." << std::endl;
}
}
TCP_服务器::TCP_服务器(boost::asio::io_服务和io_服务,int端口):
m_io_服务(io_服务),
m_接受器(io_服务,bi::tcp::endpoint(bi::tcp::v4(),端口)),
m_新建_tcp_连接(tcp_连接::创建(io_服务))
{
m_port=端口;
开始接受();
}
无效TCP_服务器::启动_接受()
{
std::cout我相信你发布的代码有点不完整/不正确。不过,这里有一些指导
(一)
您的async_accept()调用似乎错误。它应该是
m_acceptor.async_accept(m_new_tcp_connection->socket(),...)
(二)
请注意,接受套接字后将调用Handle_Accept()函数。换句话说,当控件到达Handle_Accept()时,您只需向套接字写入即可。类似于
void TCP_Server::Handle_Accept(const system::error_code& error)
{
if(!error)
{
//send data to the client
string message = "hello there!\n";
//Write data to the socket and then call the handler AFTER that
//Note, you will need to define a Handle_Write() function in your TCP_Connection class.
async_write(m_new_tcp_connection->socket(),buffer(message),bind(&TCP_Connection::Handle_Write, this,placeholders::error,placeholders::bytes_transferred));
//accept the next connection
Start_Accept();
}
}
(三)
至于客户,您应该看看这里:
< p>如果你的通信在C++中实现,你可以使用BooSooServices文库来将向量SigiLIZE化为字节,并将这些文件转换成另一台机器。在相反的一端,你将使用BooSooSooLoad LIB来对对象进行期望化。我看到至少有两种方法这样做。
Boost序列化的优点:这种方法在32位和64位系统之间传输对象时也可以使用
以下是链接:
问候,
OvanesAFAIK ASIO iostreams仅用于同步I/O。但您的示例给了我一个提示,您希望使用异步I/O。
下面是一个服务器的小示例,它使用异步I/O来读取一个请求,该请求包含一个整数数组,前面是请求中整数的4字节计数。
实际上,我把一个整数向量序列化为
计数(4字节)
int
int
...
等
如果读取ints向量成功,服务器将写入一个4字节的响应代码(=1),然后对来自客户端的新请求发出读取。话虽如此,代码如下
#include <iostream>
#include <vector>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/thread.hpp>
#include <boost/asio.hpp>
using namespace boost::asio;
using boost::asio::ip::tcp;
class Connection
{
public:
Connection(tcp::acceptor& acceptor)
: acceptor_(acceptor), socket_(acceptor.get_io_service(), tcp::v4())
{
}
void start()
{
acceptor_.get_io_service().post(boost::bind(&Connection::start_accept, this));
}
private:
void start_accept()
{
acceptor_.async_accept(socket_,boost::bind(&Connection::handle_accept, this,
placeholders::error));
}
void handle_accept(const boost::system::error_code& err)
{
if (err)
{
//Failed to accept the incoming connection.
disconnect();
}
else
{
count_ = 0;
async_read(socket_, buffer(&count_, sizeof(count_)),
boost::bind(&Connection::handle_read_count,
this, placeholders::error, placeholders::bytes_transferred));
}
}
void handle_read_count(const boost::system::error_code& err, std::size_t bytes_transferred)
{
if (err || (bytes_transferred != sizeof(count_))
{
//Failed to read the element count.
disconnect();
}
else
{
elements_.assign(count_, 0);
async_read(socket_, buffer(elements_),
boost::bind(&Connection::handle_read_elements, this,
placeholders::error, placeholders::bytes_transferred));
}
}
void handle_read_elements(const boost::system::error_code& err, std::size_t bytes_transferred)
{
if (err || (bytes_transferred != count_ * sizeof(int)))
{
//Failed to read the request elements.
disconnect();
}
else
{
response_ = 1;
async_write(socket_, buffer(&response_, sizeof(response_)),
boost::bind(&Connection::handle_write_response, this,
placeholders::error, placeholders::bytes_transferred));
}
}
void handle_write_response(const boost::system::error_code& err, std::size_t bytes_transferred)
{
if (err)
disconnect();
else
{
//Start a fresh read
count_ = 0;
async_read(socket_, buffer(&count_, sizeof(count_)),
boost::bind(&Connection::handle_read_count,
this, placeholders::error, placeholders::bytes_transferred));
}
}
void disconnect()
{
socket_.shutdown(tcp::socket::shutdown_both);
socket_.close();
socket_.open(tcp::v4());
start_accept();
}
tcp::acceptor& acceptor_;
tcp::socket socket_;
std::vector<int> elements_;
long count_;
long response_;
};
class Server : private boost::noncopyable
{
public:
Server(unsigned short port, unsigned short thread_pool_size, unsigned short conn_pool_size)
: acceptor_(io_service_, tcp::endpoint(tcp::v4(), port), true)
{
unsigned short i = 0;
for (i = 0; i < conn_pool_size; ++i)
{
ConnectionPtr conn(new Connection(acceptor_));
conn->start();
conn_pool_.push_back(conn);
}
// Start the pool of threads to run all of the io_services.
for (i = 0; i < thread_pool_size; ++i)
{
thread_pool_.create_thread(boost::bind(&io_service::run, &io_service_));
}
}
~Server()
{
io_service_.stop();
thread_pool_.join_all();
}
private:
io_service io_service_;
tcp::acceptor acceptor_;
typedef boost::shared_ptr<Connection> ConnectionPtr;
std::vector<ConnectionPtr> conn_pool_;
boost::thread_group thread_pool_;
};
boost::function0<void> console_ctrl_function;
BOOL WINAPI console_ctrl_handler(DWORD ctrl_type)
{
switch (ctrl_type)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_SHUTDOWN_EVENT:
console_ctrl_function();
return TRUE;
default:
return FALSE;
}
}
void stop_server(Server* pServer)
{
delete pServer;
pServer = NULL;
}
int main()
{
Server *pServer = new Server(10255, 4, 20);
console_ctrl_function = boost::bind(stop_server, pServer);
SetConsoleCtrlHandler(console_ctrl_handler, TRUE);
while(true)
{
Sleep(10000);
}
}
#包括
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间boost::asio;
使用boost::asio::ip::tcp;
类连接
{
公众:
连接(tcp::接受器和接受器)
:acceptor(acceptor),socket(acceptor.get_io_service(),tcp::v4())
{
}
void start()
{
acceptor_u.get_io_service().post(boost::bind(&Connection::start_accept,this));
}
私人:
void start_accept()
{
acceptor\异步\接受(socket\接受,boost::bind(&Connection::handle\接受,this,
占位符::错误);
}
无效句柄\u接受(const boost::system::error\u code&err)
{
如果(错误)
{
//无法接受传入连接。
断开连接();
}
其他的
{
计数=0;
异步读取(套接字、缓冲区(&count、sizeof(count)),
boost::bind(&Connection::handle\u read\u count),
这,占位符::错误,占位符::字节(已传输));
}
}
无效句柄\读取\计数(常量boost::系统::错误\代码和错误,std::大小\传输的字节数)
{
if(err | |(字节_传输!=sizeof(计数|))
{
//无法读取元素计数。
断开连接();
}
其他的
{
元素分配(计数,0);
异步读取(套接字、缓冲区(元素),
boost::bind(&Connection::handle\u read\u元素,此,
占位符::错误,占位符::字节(已传输);
}
}
无效句柄\u读取\u元素(常量boost::system::error\u code&err,std::size\u t字节\u传输)
{
if(err | |(字节数_传输!=计数*大小(int)))
{
//无法读取请求元素。
断开连接();
}
其他的
{
响应=1;
异步写入(套接字、缓冲区和响应、sizeof(响应)),
boost::bind(&Connection::handle_write_响应,
占位符::错误,占位符::字节(已传输);
}
}
无效句柄\写入\响应(常量boost::系统::错误\代码和错误,std::大小\传输的字节数)
{
如果(错误)
断开连接();
其他的
{
//重读
计数=0;
异步读取(套接字、缓冲区(&count、sizeof(count)),
boost::bind(&Connection::handle\u read\u count),
此,占位符::错误,占位符::b