加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
connector.hpp 4.02 KB
一键复制 编辑 原始数据 按行查看 历史
gaoqingfeng 提交于 2024-09-09 07:50 . update
#pragma once
/*
* tcp connector.
*/
#include "anet.hpp"
#include <utility>
#include "define.hpp"
#include "connection.hpp"
#include "event_loop.hpp"
#include "asio/detail/noncopyable.hpp"
namespace anet {
namespace tcp {
const unsigned int gClientStartId = 0x1<<0;
class CConnector final: asio::noncopyable {
public:
explicit CConnector(CEventLoop &loop) : m_loop(loop),
m_codec(nullptr), m_session(nullptr),
m_conn(nullptr), m_nextId(gClientStartId) {
}
virtual ~CConnector() {
connSharePtr conn = nullptr;
bool unique = false;
{
std::lock_guard<std::mutex> guard(m_mutex);
conn = m_conn;
unique = m_conn.unique();
}
(void)unique;
if (conn != nullptr) {
conn->close();
}
}
public:
void setPacketParser(ICodec *codec) {
assert(codec != nullptr && "packet parser is null");
m_codec = codec;
}
void setSession(ISession *session) {
assert(session != nullptr && "session is null");
m_session = session;
}
ISession *getSession() {
return m_session;
}
ICodec *getCodec() {
return m_codec;
}
public:
// asynchronous connect interface
bool asyncConnect(const std::string& addr, unsigned short port, connectErrCallback errCallback) {
if (m_session == nullptr || m_codec == nullptr) {
if (errCallback != nullptr) {
errCallback(addr.c_str(), port, 0);
}
LogCrit("net session or codec is null");
return false;
}
auto& ioContext = m_loop.getNextIOContext();
auto conn = std::make_shared<CConnection>(ioContext, m_loop);
asio::ip::tcp::resolver resolver(ioContext);
auto endpoints = resolver.resolve(addr, std::to_string(port));
asio::async_connect(conn->getSocket(), endpoints,
[this, conn, addr, port, callback = std::move(errCallback)](auto ec, asioEndPoint point) {
if (!ec) {
this->saveConn(conn);
conn->setRemoveFunc(std::bind(&CConnector::resetConn, this, std::placeholders::_1));
conn->doStart(m_session, m_codec);
} else {
// error callback.
if (callback != nullptr) {
callback(addr.c_str(), port, ec.value());
}
}
});
return true;
}
// save the only conn.
void saveConn(connSharePtr conn) {
std::lock_guard<std::mutex> guard(m_mutex);
auto objId = m_nextId++;
conn->SetObjId(objId);
this->m_conn = conn;
}
// reset the only conn.
void resetConn(connSharePtr conn) {
std::lock_guard<std::mutex> guard(m_mutex);
if (conn.get() != this->m_conn.get()) {
assert(false && "the two object is different");
return;
}
this->m_conn.reset();
}
// synchronous connect interface
bool syncConnect(const std::string &addr, unsigned short port) {
if (m_session == nullptr || m_codec == nullptr) {
LogCrit("net session or codec is null");
return false;
}
// create a share_ptr of CConnection.
auto &ioContext = m_loop.getNextIOContext();
auto conn = std::make_shared<CConnection>(ioContext, m_loop);
asio::ip::tcp::resolver resolver(ioContext);
auto endPoint = resolver.resolve(addr, std::to_string(port));
std::error_code ec;
auto point = asio::connect(conn->getSocket(), endPoint, ec);
(void)point; // avoid unused warning.
if (!ec) {
this->saveConn(conn);
conn->setRemoveFunc(std::bind(&CConnector::resetConn, this, std::placeholders::_1));
conn->doStart(m_session, m_codec);
return true;
} else {
LogCrit("connect to (%s:%d) error:%d", addr.c_str(), port, ec.value());
return false;
}
}
bool Close() {
std::lock_guard<std::mutex> guard(m_mutex);
if (m_conn != nullptr) {
m_conn->close();
return true;
} else {
return false;
}
}
private:
CEventLoop &m_loop;
// the user must keep the life of session and codec.
ICodec *m_codec{nullptr};
ISession *m_session{nullptr};
// save the CConnection.
mutable std::mutex m_mutex;
connSharePtr m_conn{ nullptr };
unsigned int m_nextId{ gClientStartId };
};
}
}
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化