在使用boost::asio做TCP客户端时,通过async_read_somey读取网络数据,第一次连上服务端后,可以正常读取服务端下发的数据,当服务端关闭后,async_read_some中也可以监听到事件,此时客户端类会通知它的调用者来重连服务端,此时问题来了,如果重边时不开新线程,就可以正常连上并收发数据,但是如果开了新线程,就只能连接成功,却收不到服务端下发的任何数据,也监听不到网络断开消息,不明白怎么回事,有了解的同学可以指导下吗,以下是代码,可直接运行,主要问题集中在Task::Release方法中
// TestAsio.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFFER_SIZE 1024
class Cli;
class StateListener {
public:
virtual void Release(int errCode) = 0;
};
class Cli {
public:
Cli() = delete;
Cli(const Cli&) = delete;
Cli& operator=(const Cli&) = delete;
Cli(boost::asio::io_service* io, StateListener* pInstance);
~Cli();
void start();
void stop();
private:
void handle_read();
bool m_bContinue;
bool m_bConnectSuccess;
StateListener* m_pInstance;
boost::asio::io_service* m_io;
boost::shared_ptr m_socket;
boost::asio::deadline_timer m_connect_timer;
unsigned char* m_pRecvBuf;
const int m_iRecvBufLen;
};
Cli::Cli(boost::asio::io_service* io, StateListener* pInstance)
: m_bContinue(false)
, m_io(io)
, m_pInstance(pInstance)
, m_iRecvBufLen(BUFFER_SIZE)
, m_bConnectSuccess(false)
, m_connect_timer(*io)
{
m_pRecvBuf = new unsigned char[BUFFER_SIZE];
}
Cli::~Cli()
{
delete[] m_pRecvBuf;
}
void Cli::start()
{
m_bContinue = true;
boost::asio::ip::tcp::endpoint ep(boost::asio::ip::address::from_string("127.0.0.1"), 12345);
boost::asio::ip::tcp::endpoint local_ep(boost::asio::ip::address::from_string("127.0.0.1"), 0);
boost::shared_ptr sock = boost::shared_ptr(new boost::asio::ip::tcp::socket(*m_io));
sock->open(boost::asio::ip::tcp::v4());
sock->bind(local_ep);
boost::system::error_code err;
sock->async_connect(ep, [this, sock](const boost::system::error_code& error) {
if (error)
{
std::cout << "async_connect err, " << error.message() << "\n";
m_pInstance->Release(0);
return;
}
std::cout << "connect success\n";
m_bConnectSuccess = true;
m_socket = sock;
m_connect_timer.cancel();
handle_read();
});
m_connect_timer.expires_from_now(boost::posix_time::seconds(5));
m_connect_timer.async_wait([this](const boost::system::error_code& error) {
if (!m_bConnectSuccess)
{
m_pInstance->Release(-1);
}
});
}
void Cli::stop()
{
m_bContinue = false;
if (m_socket == nullptr)
{
return;
}
if (m_socket->is_open())
{
try
{
m_socket->close();
m_socket = nullptr;
}
catch (std::exception&)
{
}
}
}
void Cli::handle_read()
{
if (!m_bContinue)
{
return;
}
m_socket->async_read_some(boost::asio::buffer(m_pRecvBuf, m_iRecvBufLen),
[this](const boost::system::error_code& error, size_t bytes_recved) {
if (!error)
{
std::cout << "recv len " << bytes_recved << std::endl;//这里打印收到的数据
handle_read();
}
else
{
if (m_pInstance)
{
m_pInstance->Release(-2);//服务端断开后会从这里通知主程序
}
}
});
}
class Task : public StateListener {
public:
Task();
~Task();
void Start();
void Stop();
virtual void Release(int errCode);
private:
void RunCli();
bool m_bContinue;
std::thread* m_pReconnTrd;
boost::asio::io_service m_io;
std::shared_ptr m_cli;
};
Task::Task()
: m_cli(nullptr)
, m_pReconnTrd(nullptr)
{
}
Task::~Task() {}
void Task::Start()
{
m_bContinue = true;
RunCli();
new std::thread([this]() {
m_io.run();
});
}
void Task::Stop()
{
m_bContinue = false;
if (m_cli != nullptr) {
m_cli->stop();
m_cli = nullptr;
}
m_io.stop();
}
void Task::RunCli() {
m_cli = std::shared_ptr(new Cli(&m_io, this));
m_cli->start();
}
/////***********************************
****** 重连逻辑在这里
****** 重连后收不到数据的问题也由这里引起
*********************************//////
void Task::Release(int err) {
printf("call Task::Release, err=%d\n", err);
if (m_cli != NULL) {
m_cli->stop();
m_cli = NULL;
}
if (m_pReconnTrd == NULL) {
m_pReconnTrd = new std::thread([this]() {//如果在线程中重连,连上后就收不到数据
int sec = 0;
while (m_bContinue) {
std::this_thread::sleep_for(std::chrono::seconds(1));
printf("sec=%d\n", sec);
if (++sec >= 10) {
m_pReconnTrd = NULL;
//new std::thread(&Task::RunCli, this);//此处也一样,如果开新线程,连上后也收不到数据
RunCli();
break;
}
}
std::cout << "exit reconn thread\n";
});
}
}
int main()
{
Task t;
t.Start();
char c;
while ((c = getchar()) != 'q') {
getchar();
}
t.Stop();
return 0;
}