我在C ++ TCP Server中有问题(使用boost asio)。
在普通客户端中,许多客户端连接到服务器是正常的。
但是,如果每个客户端以每秒10次的速度连接和断开服务器,则服务器会花费一些时间。
void ClientConnection::start()
{
socket_.async_read_some(boost::asio::buffer(buffer_),
strand_.wrap(
boost::bind(&connection::handle_read, shared_from_this(),
boost::asio::placeholders::error,
boost::asio::placeholders::bytes_transferred)));
}
void ClientConnection::closeSocket() {
mStrand.post(boost::bind(&ClientConnection::innerCloseSocket, this->shared_from_this()));
}
void ClientConnection::innerCloseSocket() {
boost::system::error_code error;
mSocket.close(error);
LOG_INFO("Close client[" << mClientId << "] socket connection"); //line:216
}
ClientConnection::~ClientConnection() {
}
void ClientConnection::handle_read(const boost::system::error_code& e,
std::size_t bytes_transferred)
{
if (!e)
{
//read data and use it
}
else { //error occurs
closeSocket();
boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
cmd->setClient(this->weak_from_this()); //here set this connection weak_ptr
putCmd(cmd); //do something in other thread.
}
}
void ClientConnection::handle_write(const boost::system::error_code& e)
{
if (!e)
{
//send data
}
else { //error occurs
closeSocket();
boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
cmd->setClient(this->weak_from_this()); //here set this connection weak_ptr
putCmd(cmd); //do something in other thread.
}
}
但是,当许多客户端连接到服务器时,服务器是核心。核心就像一个连接被破坏了两次,内存是错误的。
#0 0x00007f6e3aa561f7 in raise () from /lib64/libc.so.6
#1 0x00007f6e3aa578e8 in abort () from /lib64/libc.so.6
#2 0x00007f6e3b35c9d5 in __gnu_cxx::__verbose_terminate_handler() () from /lib64/libstdc++.so.6
#3 0x00007f6e3b35a946 in ?? () from /lib64/libstdc++.so.6
#4 0x00007f6e3b35a973 in std::terminate() () from /lib64/libstdc++.so.6
#5 0x00007f6e3b35ab93 in __cxa_throw () from /lib64/libstdc++.so.6
#6 0x00007f6e3b35b12d in operator new(unsigned long) () from /lib64/libstdc++.so.6
#7 0x00007f6e3b3b9c79 in std::string::_Rep::_S_create(unsigned long, unsigned long, std::allocator<char> const&) () from /lib64/libstdc++.so.6
#8 0x00007f6e3b3ba8bb in std::string::_Rep::_M_clone(std::allocator<char> const&, unsigned long) () from /lib64/libstdc++.so.6
#9 0x00007f6e3b3ba964 in std::string::reserve(unsigned long) () from /lib64/libstdc++.so.6
#10 0x00007f6e3b3baa28 in std::string::append(std::string const&) () from /lib64/libstdc++.so.6
#11 0x00007f6e3be5c4c8 in log4cxx::helpers::CharMessageBuffer::operator<< (this=0x7f6e20ff8750, msg=...) at messagebuffer.cpp:31
#12 0x00000000008a3a05 in ClientConnection::internalCloseSocket (this=0x7f6e046fefd0) at src/business/ClientConnection.cpp:216
#13 0x00000000008b620a in boost::_mfi::mf0<void, ClientConnection>::call<boost::shared_ptr<ClientConnection> > (this=0x7f6e20ff89c0, u=...)
at externals/boost/include/boost/bind/mem_fn_template.hpp:40
#14 0x00000000008b5c79 in boost::_mfi::mf0<void, ClientConnection>::operator()<boost::shared_ptr<ClientConnection> > (this=0x7f6e20ff89c0, u=...)
at externals/boost/include/boost/bind/mem_fn_template.hpp:55
#15 0x00000000008b5416 in boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > >::operator()<boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list0> (
this=0x7f6e20ff89d0, f=..., a=...) at externals/boost/include/boost/bind/bind.hpp:259
#16 0x00000000008b4997 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > >::operator() (this=0x7f6e20ff89c0) at externals/boost/include/boost/bind/bind.hpp:1294
#17 0x00000000008b3667 in boost::asio::asio_handler_invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > > (function=...) at externals/boost/include/boost/asio/handler_invoke_hook.hpp:69
#18 0x00000000008b235a in boost_asio_handler_invoke_helpers::invoke<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > >, boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > > (
function=..., context=...) at externals/boost/include/boost/asio/detail/handler_invoke_helpers.hpp:37
#19 0x00000000008b0ee3 in boost::asio::detail::completion_handler<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ClientConnection>, boost::_bi::list1<boost::_bi::value<boost::shared_ptr<ClientConnection> > > > >::do_complete (owner=0x1a5a5c0, base=0x7f6e28018f30) at externals/boost/include/boost/asio/detail/completion_handler.hpp:68
#20 0x00000000007c3ef4 in boost::asio::detail::task_io_service_operation::complete (this=0x7f6e28018f30, owner=..., ec=..., bytes_transferred=0)
at externals/boost/include/boost/asio/detail/task_io_service_operation.hpp:38
#21 0x00000000007c7937 in boost::asio::detail::strand_service::do_complete (owner=0x1a5a5c0, base=0x7f6df001ab40, ec=...) at externals/boost/include/boost/asio/detail/impl/strand_service.ipp:167
#22 0x00000000007c3ef4 in boost::asio::detail::task_io_service_operation::complete (this=0x7f6df001ab40, owner=..., ec=..., bytes_transferred=0)
at externals/boost/include/boost/asio/detail/task_io_service_operation.hpp:38
#23 0x00000000007c5dde in boost::asio::detail::task_io_service::do_run_one (this=0x1a5a5c0, lock=..., this_thread=..., ec=...) at externals/boost/include/boost/asio/detail/impl/task_io_service.ipp:372
#24 0x00000000007c5845 in boost::asio::detail::task_io_service::run (this=0x1a5a5c0, ec=...) at externals/boost/include/boost/asio/detail/impl/task_io_service.ipp:149
#25 0x00000000007c60cf in boost::asio::io_service::run (this=0x1a54b10) at externals/boost/include/boost/asio/impl/io_service.ipp:59
#26 0x00000000008c27b6 in ProcessModule::threadRun (this=0x1a54b10) at src/business/ProcessModule.cpp:149
#27 0x00000000008c82e7 in boost::_mfi::mf0<void, ProcessModule>::operator() (this=0x1b0aee8, p=0x1a54b10) at externals/boost/include/boost/bind/mem_fn_template.hpp:49
#28 0x00000000008c824a in boost::_bi::list1<boost::_bi::value<ProcessModule*> >::operator()<boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list0> (this=0x1b0aef8,
f=..., a=...) at externals/boost/include/boost/bind/bind.hpp:259
#29 0x00000000008c81f9 in boost::_bi::bind_t<void, boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list1<boost::_bi::value<ProcessModule*> > >::operator() (
this=0x1b0aee8) at externals/boost/include/boost/bind/bind.hpp:1294
#30 0x00000000008c811a in boost::detail::thread_data<boost::_bi::bind_t<void, boost::_mfi::mf0<void, ProcessModule>, boost::_bi::list1<boost::_bi::value<ProcessModule*> > > >::run (this=0x1b0ad30) at externals/boost/include/boost/thread/detail/thread.hpp:116
(gdb) p *this
$1 = {<boost::enable_shared_from_this<ClientConnection>> = {weak_this_ = {px = 0x7f981c4cf720, pn = {pi_ = 0x7f981c2feca0}}}, <boost::noncopyable_::noncopyable> = {<No data fields>},
mIoService = @0x1333b10,
mSocket = {<boost::asio::basic_socket<boost::asio::ip::tcp, boost::asio::stream_socket_service<boost::asio::ip::tcp> >> = {<boost::asio::basic_io_object<boost::asio::stream_socket_service<boost::asio::ip::tcp>, true>> = {implementation = {<boost::asio::detail::reactive_socket_service_base::base_implementation_type> = {socket_ = -1, state_ = 0 '\000', reactor_data_ = 0x0}, protocol_ = {family_ = 2}},
service_ = 0x1371560}, <boost::asio::socket_base> = {static message_peek = 2, static message_out_of_band = 1, static message_do_not_route = 4, static message_end_of_record = 128,
static max_connections = 128}, <No data fields>}, <No data fields>}, mStrand = {service_ = @0x13e5510, impl_ = 0x7f98080500a0},
LOG_INFO("Close client[" << mClientId << "] socket connection");//line:216
mClientId是错误的值。看来此类已被破坏。
(gdb) frame 12
(gdb) p *(weak_this_.pn.pi_)
$3 = {_vptr.sp_counted_base = 0x957710 <vtable for boost::detail::sp_counted_impl_p<ClientConnection>+16>, use_count_ = {_M_i = 3}, weak_count_ = {_M_i = 2}}
我已经在互联网上进行搜索,找到https://www.boost.org/doc/libs/1_45_0/doc/html/boost_asio/example/http/server3/connection.cpp
示例中的注释如下:
int handle_read:
// If an error occurs then no new asynchronous operations are started. This
// means that all shared_ptr references to the connection object will
// disappear and the object will be destroyed automatically after this
// handler returns. The connection class's destructor closes the socket.
int handle_write:
// No new asynchronous operations are started. This means that all shared_ptr
// references to the connection object will disappear and the object will be
// destroyed automatically after this handler returns. The connection class's
// destructor closes the socket.
(i)如果handle_read / handle_write中发生错误,是否应该在其他线程中使用此连接weak_ptr?
(ii)ClientConnection类的生命周期是在Asio中,并且受Asio控制,我的代码有什么问题?
(iii)我认为它不能使用stand.post()和connection的weak_ptr来做某事。应该修改如下代码?
void ClientConnection::handle_read(const boost::system::error_code& e,
std::size_t bytes_transferred)
{
if (!e)
{
//read data and use it
}
else { //error occurs
//closeSocket();
//boost::shared_ptr<DisConnectCommand> cmd(new DisConnectCommand());
//cmd->setClient(this->weak_from_this()); //here set this connection weak_ptr
//putCmd(cmd); //do something in other thread.
//just close socket
boost::system::error_code error;
mSocket.close(error);
}
}
我在线,期待您的帮助。
谢谢。最好的祝福。