|
@@ -1,2398 +1,2459 @@
|
|
|
-/**
|
|
|
- * Tencent is pleased to support the open source community by making Tars available.
|
|
|
- *
|
|
|
- * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
|
|
|
- *
|
|
|
- * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
|
|
|
- * in compliance with the License. You may obtain a copy of the License at
|
|
|
- *
|
|
|
- * https://opensource.org/licenses/BSD-3-Clause
|
|
|
- *
|
|
|
- * Unless required by applicable law or agreed to in writing, software distributed
|
|
|
- * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
|
- * CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
|
- * specific language governing permissions and limitations under the License.
|
|
|
- */
|
|
|
-
|
|
|
-#ifndef __TARS_TC_EPOLL_SERVER_H_
|
|
|
-#define __TARS_TC_EPOLL_SERVER_H_
|
|
|
-
|
|
|
-#include <string>
|
|
|
-#include <memory>
|
|
|
-#include <map>
|
|
|
-#include <unordered_map>
|
|
|
-#include <vector>
|
|
|
-#include <list>
|
|
|
-#include <algorithm>
|
|
|
-#include <functional>
|
|
|
-#include "util/tc_epoller.h"
|
|
|
-#include "util/tc_thread.h"
|
|
|
-#include "util/tc_clientsocket.h"
|
|
|
-#include "util/tc_logger.h"
|
|
|
-#include "util/tc_common.h"
|
|
|
-#include "util/tc_network_buffer.h"
|
|
|
-#include "util/tc_cas_queue.h"
|
|
|
-#include "util/tc_openssl.h"
|
|
|
-
|
|
|
-using namespace std;
|
|
|
-
|
|
|
-namespace tars
|
|
|
-{
|
|
|
-
|
|
|
-/////////////////////////////////////////////////
|
|
|
-/**
|
|
|
- * @file tc_epoll_server.h
|
|
|
- * @brief EpollServer类
|
|
|
- * @brief EpollServer Class
|
|
|
- *
|
|
|
- */
|
|
|
-/////////////////////////////////////////////////
|
|
|
-/**
|
|
|
- * Server基类
|
|
|
- * Server Basic Class
|
|
|
- * 注册协议解析器
|
|
|
- * Register Protocol Resolver
|
|
|
- * 注册逻辑处理器
|
|
|
- * Register Logical Processor
|
|
|
- * 注册管理端口处理器
|
|
|
- * Register Management Port Processor
|
|
|
- */
|
|
|
-
|
|
|
-class PropertyReport;
|
|
|
-
|
|
|
-class TC_EpollServer : public TC_HandleBase
|
|
|
-{
|
|
|
-public:
|
|
|
-
|
|
|
- enum EM_CLOSE_T
|
|
|
- {
|
|
|
- /**Client active shutdown*/
|
|
|
- EM_CLIENT_CLOSE = 0, //客户端主动关闭
|
|
|
- /**The service-side business proactively calls 'close' to close the connection,
|
|
|
- * or the framework proactively closes the connection due to an exception.*/
|
|
|
- EM_SERVER_CLOSE = 1, //服务端业务主动调用close关闭连接,或者框架因某种异常主动关闭连接
|
|
|
- /**Connection timed out, server actively closed*/
|
|
|
- EM_SERVER_TIMEOUT_CLOSE = 2 //连接超时了,服务端主动关闭
|
|
|
- };
|
|
|
-
|
|
|
- enum
|
|
|
- {
|
|
|
- /**Empty connection timeout (ms)*/
|
|
|
- MIN_EMPTY_CONN_TIMEOUT = 2*1000, /*空链接超时时间(ms)*/
|
|
|
- /**The size of received buffer of the default data*/
|
|
|
- DEFAULT_RECV_BUFFERSIZE = 64*1024 /*缺省数据接收buffer的大小*/
|
|
|
- };
|
|
|
-
|
|
|
- //定义加入到网络线程的fd类别
|
|
|
- //Define the FD categories added to network threads
|
|
|
- enum CONN_TYPE
|
|
|
- {
|
|
|
- TCP_CONNECTION = 0,
|
|
|
- UDP_CONNECTION = 1,
|
|
|
- };
|
|
|
-
|
|
|
- /**
|
|
|
- * 定义协议解析接口的操作对象
|
|
|
- * 注意必须是线程安全的或是可以重入的
|
|
|
- * Define the Operating Object of the Protocol Resolution Interface
|
|
|
- * Note that it must be thread safe or reentrant
|
|
|
- */
|
|
|
- typedef std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer::PACKET_TYPE, vector<char>&)> header_filter_functor;
|
|
|
-
|
|
|
- class NetThread;
|
|
|
- class Connection;
|
|
|
- class BindAdapter;
|
|
|
- typedef TC_AutoPtr<BindAdapter> BindAdapterPtr;
|
|
|
-
|
|
|
- class Handle;
|
|
|
- typedef TC_AutoPtr<Handle> HandlePtr;
|
|
|
-
|
|
|
- class RecvContext;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送包的上下文
|
|
|
- * 由RecvContext创建出来
|
|
|
- * Context of sending packets
|
|
|
- * Created by RecvContext
|
|
|
- */
|
|
|
- class SendContext
|
|
|
- {
|
|
|
- public:
|
|
|
- SendContext(const shared_ptr<RecvContext> &context, char cmd) : _context(context), _cmd(cmd)
|
|
|
- {
|
|
|
- _sbuffer = std::make_shared<TC_NetWorkBuffer::Buffer>();
|
|
|
- }
|
|
|
-
|
|
|
- const shared_ptr<RecvContext> &getRecvContext() { return _context; }
|
|
|
- const shared_ptr<TC_NetWorkBuffer::Buffer> & buffer() { return _sbuffer; }
|
|
|
- char cmd() const { return _cmd; }
|
|
|
- uint32_t uid() const { return _context->uid(); }
|
|
|
- int fd() const { return _context->fd(); }
|
|
|
- const string &ip() const { return _context->ip(); }
|
|
|
- uint16_t port() const { return _context->port(); }
|
|
|
-
|
|
|
- friend class RecvContext;
|
|
|
-
|
|
|
- protected:
|
|
|
- shared_ptr<RecvContext> _context;
|
|
|
- /**Send package is valid. Command: 'c', close FD; 's', data need to be sent*/
|
|
|
- char _cmd; /**send包才有效, 命令:'c',关闭fd; 's',有数据需要发送*/
|
|
|
- /**Sent context*/
|
|
|
- shared_ptr<TC_NetWorkBuffer::Buffer> _sbuffer; /**发送的内容*/
|
|
|
- };
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- /**
|
|
|
- * 接收包的上下文
|
|
|
- * Context of receiving package
|
|
|
- */
|
|
|
- class RecvContext : public std::enable_shared_from_this<RecvContext>
|
|
|
- {
|
|
|
- public:
|
|
|
- RecvContext(uint32_t uid, const string &ip, int64_t port, int fd, const BindAdapterPtr &adapter, bool isClosed = false, int closeType = EM_CLIENT_CLOSE)
|
|
|
- : _uid(uid), _ip(ip), _port(port), _fd(fd), _adapter(adapter), _isClosed(isClosed), _closeType(closeType), _recvTimeStamp(TNOWMS)
|
|
|
- {
|
|
|
- }
|
|
|
- uint32_t uid() const { return _uid; }
|
|
|
- const string &ip() const { return _ip; }
|
|
|
- uint16_t port() const { return _port; }
|
|
|
- vector<char> &buffer() { return _rbuffer; }
|
|
|
- const vector<char> &buffer() const { return _rbuffer; }
|
|
|
-
|
|
|
- int64_t recvTimeStamp() const { return _recvTimeStamp; }
|
|
|
- bool isOverload() const { return _isOverload; }
|
|
|
- void setOverload() { _isOverload = true; }
|
|
|
- bool isClosed() const { return _isClosed; }
|
|
|
- int fd() const { return _fd; }
|
|
|
- BindAdapterPtr &adapter() { return _adapter; }
|
|
|
- int closeType() const { return _closeType; }
|
|
|
- void setCloseType(int closeType) { _closeType = closeType;}
|
|
|
-
|
|
|
- shared_ptr<SendContext> createSendContext() { return std::make_shared<SendContext>(shared_from_this(), 's'); }
|
|
|
- shared_ptr<SendContext> createCloseContext() { return std::make_shared<SendContext>(shared_from_this(), 'c'); }
|
|
|
-
|
|
|
- protected:
|
|
|
- /**Connection Label*/
|
|
|
- uint32_t _uid; /**连接标示*/
|
|
|
- /**IP for remote connection*/
|
|
|
- string _ip; /**远程连接的ip*/
|
|
|
- /**Port for remote connection*/
|
|
|
- uint16_t _port; /**远程连接的端口*/
|
|
|
- /**Save the FD that generated the message to select the network thread when returning the package*/
|
|
|
- int _fd; /*保存产生该消息的fd,用于回包时选择网络线程*/
|
|
|
- /**Message identifying which adapter*/
|
|
|
- BindAdapterPtr _adapter; /**标识哪一个adapter的消息*/
|
|
|
- /**Received message*/
|
|
|
- vector<char> _rbuffer; /**接收的内容*/
|
|
|
- /**Is overloaded*/
|
|
|
- bool _isOverload = false; /**是否已过载 */
|
|
|
- /**Is closed*/
|
|
|
- bool _isClosed = false; /**是否已关闭*/
|
|
|
- /**If the message package is closed, the type of closure is identified,
|
|
|
- * 0: the client actively closes,
|
|
|
- * 1: the server actively closes,
|
|
|
- * 2: the connection timeout server actively closes.
|
|
|
- * */
|
|
|
- int _closeType; /*如果是关闭消息包,则标识关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭*/
|
|
|
- /**Time to receive data*/
|
|
|
- int64_t _recvTimeStamp; /**接收到数据的时间*/
|
|
|
- };
|
|
|
-
|
|
|
-// typedef TC_CasQueue<shared_ptr<RecvContext>> recv_queue;
|
|
|
- typedef TC_ThreadQueue<shared_ptr<RecvContext>> recv_queue;
|
|
|
-// typedef TC_CasQueue<shared_ptr<SendContext>> send_queue;
|
|
|
- typedef TC_ThreadQueue<shared_ptr<SendContext>> send_queue;
|
|
|
- typedef recv_queue::queue_type recv_queue_type;
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- /**
|
|
|
- * 链接状态
|
|
|
- * Connection state
|
|
|
- */
|
|
|
- struct ConnStatus
|
|
|
- {
|
|
|
- string ip;
|
|
|
- int32_t uid;
|
|
|
- uint16_t port;
|
|
|
- int timeout;
|
|
|
- int iLastRefreshTime;
|
|
|
- size_t recvBufferSize;
|
|
|
- size_t sendBufferSize;
|
|
|
- };
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- /**
|
|
|
- * @brief 定义服务逻辑处理的接口
|
|
|
- * @brief Define interfaces for logical processing of services
|
|
|
- *
|
|
|
- */
|
|
|
- /**
|
|
|
- * 服务的逻辑处理代码
|
|
|
- * Logical Processing Code for Services
|
|
|
- */
|
|
|
- class Handle : public TC_Thread, public TC_HandleBase
|
|
|
- {
|
|
|
- public:
|
|
|
- /**
|
|
|
- * 构造, 默认没有请求, 等待10s
|
|
|
- * Constructor, default no request, wait 10s
|
|
|
- */
|
|
|
- Handle();
|
|
|
-
|
|
|
- /**
|
|
|
- * 析构函数
|
|
|
- * Destructor
|
|
|
- */
|
|
|
- virtual ~Handle();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取服务
|
|
|
- * Get Service
|
|
|
- * @return TC_EpollServer*
|
|
|
- */
|
|
|
- TC_EpollServer* getEpollServer() const { return _pEpollServer; };
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取adapter
|
|
|
- * Get adapter
|
|
|
- * @return
|
|
|
- */
|
|
|
- BindAdapter *getBindAdapter() const { return _bindAdapter; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取Handle的索引(0~handle个数-1)
|
|
|
- * Get the index of Handle(0~handle count-1)
|
|
|
- * @return
|
|
|
- */
|
|
|
- uint32_t getHandleIndex() const { return _handleIndex; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置网络线程
|
|
|
- * Set up network thread
|
|
|
- */
|
|
|
- void setNetThread(NetThread *netThread);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取网络线程
|
|
|
- * Get network thread
|
|
|
- * @return
|
|
|
- */
|
|
|
- NetThread *getNetThread() { return _netThread; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理
|
|
|
- * Process
|
|
|
- */
|
|
|
- void process(shared_ptr<RecvContext> data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 线程处理方法
|
|
|
- * Thread processing method
|
|
|
- */
|
|
|
- virtual void run();
|
|
|
-
|
|
|
- public:
|
|
|
- /**
|
|
|
- * 发送数据
|
|
|
- * Send data
|
|
|
- * @param stRecvData
|
|
|
- * @param sSendBuffer
|
|
|
- */
|
|
|
- void sendResponse(const shared_ptr<SendContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 关闭链接
|
|
|
- * Close connection
|
|
|
- * @param stRecvData
|
|
|
- */
|
|
|
- void close(const shared_ptr<RecvContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置等待时间
|
|
|
- * Set up waiting time
|
|
|
- * @param iWaitTime
|
|
|
- */
|
|
|
- void setWaitTime(uint32_t iWaitTime);
|
|
|
-
|
|
|
- /**
|
|
|
- * 对象初始化
|
|
|
- * Object initialization
|
|
|
- */
|
|
|
- virtual void initialize() {};
|
|
|
-
|
|
|
- /**
|
|
|
- * 唤醒handle对应的处理线程
|
|
|
- * Wake up the process thread corresponding to the handle
|
|
|
- */
|
|
|
- virtual void notifyFilter();
|
|
|
-
|
|
|
- /**
|
|
|
- * 心跳(每处理完一个请求或者等待请求超时都会调用一次)
|
|
|
- * Heartbeat(Called every time a request has been processed or the waiting request has timed out)
|
|
|
- */
|
|
|
- virtual void heartbeat() {}
|
|
|
-
|
|
|
- protected:
|
|
|
- /**
|
|
|
- * 具体的处理逻辑
|
|
|
- * Specific processing logic
|
|
|
- */
|
|
|
- virtual void handleImp();
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理函数
|
|
|
- * Processing Function
|
|
|
- * @param stRecvData: 接收到的数据
|
|
|
- * @param stRecvData: received data
|
|
|
- */
|
|
|
- virtual void handle(const shared_ptr<RecvContext> &data) = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理超时数据, 即数据在队列中的时间已经超过
|
|
|
- * 默认直接关闭连接
|
|
|
- * Processing timeout data, i.e. data has been queued longer than
|
|
|
- * Close connection directly by default
|
|
|
- * @param stRecvData: 接收到的数据
|
|
|
- * @param stRecvData: received data
|
|
|
- */
|
|
|
- virtual void handleTimeout(const shared_ptr<TC_EpollServer::RecvContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理连接关闭通知,包括
|
|
|
- * Handle connection shutdown notifications, including:
|
|
|
- * 1.close by peer
|
|
|
- * 2.recv/send fail
|
|
|
- * 3.close by timeout or overload
|
|
|
- * @param stRecvData:
|
|
|
- */
|
|
|
- virtual void handleClose(const shared_ptr<TC_EpollServer::RecvContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理overload数据 即数据队列中长度已经超过允许值
|
|
|
- * 默认直接关闭连接
|
|
|
- * Processing overload data means that the length of the data queue has exceeded the allowable value
|
|
|
- * Close connection directly by default
|
|
|
- * @param stRecvData: 接收到的数据
|
|
|
- * @param stRecvData: received data
|
|
|
- */
|
|
|
- virtual void handleOverload(const shared_ptr<TC_EpollServer::RecvContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理异步回调队列
|
|
|
- * Handle asynchronous callback queues
|
|
|
-
|
|
|
- */
|
|
|
- virtual void handleAsyncResponse() {}
|
|
|
-
|
|
|
- /**
|
|
|
- * handleFilter拆分的第二部分,处理用户自有数据
|
|
|
- * 非游戏逻辑可忽略bExpectIdle参数
|
|
|
- * The second part of handleFilter splitting, dealing with user-owned data
|
|
|
- * Non-game logic ignores bExpectIdle parameter
|
|
|
- */
|
|
|
- virtual void handleCustomMessage(bool bExpectIdle = false) {}
|
|
|
-
|
|
|
- /**
|
|
|
- * 线程已经启动, 进入具体处理前调用
|
|
|
- * Thread has been started and called before entering specific processing
|
|
|
- */
|
|
|
- virtual void startHandle() {}
|
|
|
-
|
|
|
- /**
|
|
|
- * 线程马上要退出时调用
|
|
|
- * Call when the thread is about to exit
|
|
|
- */
|
|
|
- virtual void stopHandle() {}
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否所有的Adpater队列都为空
|
|
|
- * Whether all adapter queues are empty.
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- virtual bool allAdapterIsEmpty();
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否所有的servant都没有resp消息待处理
|
|
|
- * Whether all servant don't have resp message to deal.
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- virtual bool allFilterIsEmpty();
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置服务
|
|
|
- * Set up service
|
|
|
- * @param pEpollServer
|
|
|
- */
|
|
|
- void setEpollServer(TC_EpollServer *pEpollServer);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置Adapter
|
|
|
- * Set up Apdater
|
|
|
- * @param pEpollServer
|
|
|
- */
|
|
|
- void setBindAdapter(BindAdapter* bindAdapter);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置index
|
|
|
- * Set up index
|
|
|
- * @param index
|
|
|
- */
|
|
|
- void setHandleIndex(uint32_t index);
|
|
|
-
|
|
|
- /**
|
|
|
- * 等待在队列上
|
|
|
- * On the waiting queue
|
|
|
- */
|
|
|
- void wait();
|
|
|
-
|
|
|
- /**
|
|
|
- * 从队列中获取数据
|
|
|
- * Receive data from the queue
|
|
|
- * @param recv
|
|
|
- * @return
|
|
|
- */
|
|
|
- bool popRecvQueue(shared_ptr<RecvContext> &recv);
|
|
|
-
|
|
|
- /**
|
|
|
- * 友元类
|
|
|
- * Friend Class
|
|
|
- */
|
|
|
- friend class BindAdapter;
|
|
|
- protected:
|
|
|
- /**
|
|
|
- * 服务
|
|
|
- * Service
|
|
|
- */
|
|
|
- TC_EpollServer *_pEpollServer;
|
|
|
-
|
|
|
- /**
|
|
|
- * handle对应的网路线程(网络线程和handle线程合并的情况下有效)
|
|
|
- * Network threads corresponding to handle (valid when network threads and handle threads are merged)
|
|
|
- */
|
|
|
- NetThread *_netThread = NULL;
|
|
|
-
|
|
|
- /**
|
|
|
- * 所属handle组
|
|
|
- * The handle group to which one belongs
|
|
|
- */
|
|
|
- BindAdapter* _bindAdapter;
|
|
|
-
|
|
|
- /**
|
|
|
- * 等待时间
|
|
|
- * Waiting time
|
|
|
- */
|
|
|
- uint32_t _iWaitTime;
|
|
|
-
|
|
|
- /**
|
|
|
- * Handle的索引
|
|
|
- * Index of the Handle
|
|
|
- */
|
|
|
- uint32_t _handleIndex;
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- using close_functor = std::function<void (void*, EM_CLOSE_T )>;
|
|
|
- using auth_process_wrapper_functor = std::function<bool (Connection *c, const shared_ptr<RecvContext> &recv )>;
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- // 服务端口管理,监听socket信息
|
|
|
- // Service port management, listening for socket information
|
|
|
- class BindAdapter : public TC_HandleBase
|
|
|
- {
|
|
|
- public:
|
|
|
- /**
|
|
|
- * 缺省的一些定义
|
|
|
- * Defualt definitions
|
|
|
- */
|
|
|
- enum
|
|
|
- {
|
|
|
- /**Flow*/
|
|
|
- DEFAULT_QUEUE_CAP = 10*1024, /**流量*/
|
|
|
- /**Queue minimum timeout (ms)*/
|
|
|
- MIN_QUEUE_TIMEOUT = 3*1000, /**队列最小超时时间(ms)*/
|
|
|
- /**Default maximum connections*/
|
|
|
- DEFAULT_MAX_CONN = 1024, /**缺省最大连接数*/
|
|
|
- /**Default queue timeout (ms)*/
|
|
|
- DEFAULT_QUEUE_TIMEOUT = 60*1000, /**缺省的队列超时时间(ms)*/
|
|
|
- };
|
|
|
- /**
|
|
|
- * 顺序
|
|
|
- * Order
|
|
|
- */
|
|
|
- enum EOrder
|
|
|
- {
|
|
|
- ALLOW_DENY,
|
|
|
- DENY_ALLOW
|
|
|
- };
|
|
|
-
|
|
|
- /**
|
|
|
- * 数据队列
|
|
|
- * Data Queue
|
|
|
- */
|
|
|
- struct DataQueue
|
|
|
- {
|
|
|
- /**
|
|
|
- * 接收的数据队列
|
|
|
- * Received data queue
|
|
|
- */
|
|
|
- recv_queue _rbuffer;
|
|
|
-
|
|
|
- /**
|
|
|
- * 锁
|
|
|
- * Lock
|
|
|
- */
|
|
|
- TC_ThreadLock _monitor;
|
|
|
- };
|
|
|
-
|
|
|
- /**
|
|
|
- * 构造函数
|
|
|
- * Constructor
|
|
|
- */
|
|
|
- BindAdapter(TC_EpollServer *pEpollServer);
|
|
|
-
|
|
|
- /**
|
|
|
- * 析够函数
|
|
|
- * Destructor
|
|
|
- */
|
|
|
- ~BindAdapter();
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置需要手工监听
|
|
|
- * Set requires manual listening
|
|
|
- */
|
|
|
- void enableManualListen() { _manualListen = true; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否手工监听端口
|
|
|
- * Whether to manual listen the port or not
|
|
|
- * @return
|
|
|
- */
|
|
|
- bool isManualListen() const { return _manualListen; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 手工绑定端口
|
|
|
- * Manual port binding
|
|
|
- */
|
|
|
- void manualListen();
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置adapter name
|
|
|
- * Set up adapter name
|
|
|
- * @param name
|
|
|
- */
|
|
|
- void setName(const string &name);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取adapter name
|
|
|
- * Get adapter name
|
|
|
- * @return string
|
|
|
- */
|
|
|
- string getName() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 增加处理线程对应的接收队列
|
|
|
- * Add the corresponding receiving queue for processing threads
|
|
|
- * @return string
|
|
|
- */
|
|
|
- void initThreadRecvQueue(uint32_t handeIndex);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取queue capacity
|
|
|
- * Get queue capacity
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getQueueCapacity() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置queue capacity
|
|
|
- * Set up queue capacity
|
|
|
- * @param n
|
|
|
- */
|
|
|
- void setQueueCapacity(int n);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置协议名称
|
|
|
- * Set up the protocol name
|
|
|
- * @param name
|
|
|
- */
|
|
|
- void setProtocolName(const string& name);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取协议名称
|
|
|
- * Get the protocol name
|
|
|
- * @return const string&
|
|
|
- */
|
|
|
- const string& getProtocolName();
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否tars协议
|
|
|
- * Whether it is the tars protocol
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool isTarsProtocol();
|
|
|
-
|
|
|
- /**
|
|
|
- * 判断是否需要过载保护
|
|
|
- * Determine whether it needs overload protection
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- int isOverloadorDiscard();
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置消息在队列中的超时时间, t为毫秒
|
|
|
- * (超时时间精度只能是s)
|
|
|
- * Set the timeout time of the message in the queue, t is milliseconds
|
|
|
- * (timeout precision can only be s)
|
|
|
- *
|
|
|
- * @param t
|
|
|
- */
|
|
|
- void setQueueTimeout(int t);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取消息在队列中的超时时间, 毫秒
|
|
|
- * Get timeout of message in queue, MS
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getQueueTimeout() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置endpoint
|
|
|
- * Set up endpoint
|
|
|
- * @param str
|
|
|
- */
|
|
|
- void setEndpoint(const string &str);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取ip
|
|
|
- * Get ip
|
|
|
- * @return const string&
|
|
|
- */
|
|
|
- TC_Endpoint getEndpoint() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 监听socket
|
|
|
- * Listen socket
|
|
|
- * @return TC_Socket
|
|
|
- */
|
|
|
- TC_Socket &getSocket();
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置最大连接数
|
|
|
- * Set the maximum connection number
|
|
|
- * @param iMaxConns
|
|
|
- */
|
|
|
- void setMaxConns(int iMaxConns);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取最大连接数
|
|
|
- * Get the maximum connection number
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- size_t getMaxConns() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置HeartBeat时间
|
|
|
- * Set the HeartBeat time
|
|
|
- * @param n
|
|
|
- */
|
|
|
- void setHeartBeatTime(time_t t);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取HeartBeat时间
|
|
|
- * Get the HeartBeat time
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- time_t getHeartBeatTime() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置allow deny次序
|
|
|
- * Set the allow deny order
|
|
|
- * @param eOrder
|
|
|
- */
|
|
|
- void setOrder(EOrder eOrder);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置允许ip
|
|
|
- * Set allowed ip
|
|
|
- * @param vtAllow
|
|
|
- */
|
|
|
- void setAllow(const vector<string> &vtAllow);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置禁止ip
|
|
|
- * Set the disabled ip
|
|
|
- * @param vtDeny
|
|
|
- */
|
|
|
- void setDeny(const vector<string> &vtDeny);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取允许ip
|
|
|
- * Get the allowed ip
|
|
|
- * @return vector<string>: ip列表
|
|
|
- * @return vector<string>: ip list
|
|
|
- */
|
|
|
- const vector<string> &getAllow() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取禁止ip
|
|
|
- * Get the disable ip
|
|
|
- * @return vector<string>: ip列表
|
|
|
- * @return vector<string>: ip list
|
|
|
- */
|
|
|
- const vector<string> &getDeny() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取allow deny次序
|
|
|
- * Get the allow deny order
|
|
|
- * @return EOrder
|
|
|
- */
|
|
|
- EOrder getOrder() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否Ip被允许
|
|
|
- * Whether the ip is allowed or not
|
|
|
- * @param ip
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool isIpAllow(const string& ip) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否超过了最大连接数
|
|
|
- * Whether it exceeds the maximum connection number
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool isLimitMaxConnection() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 减少当前连接数
|
|
|
- * Reduce current connections
|
|
|
- */
|
|
|
- void decreaseNowConnection();
|
|
|
-
|
|
|
- /**
|
|
|
- * 增加当前连接数
|
|
|
- * Increase current connections
|
|
|
- */
|
|
|
- void increaseNowConnection();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取所有链接状态
|
|
|
- * Get all connection states
|
|
|
- * @return ConnStatus
|
|
|
- */
|
|
|
- vector<ConnStatus> getConnStatus();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取当前连接数
|
|
|
- * Get current connections
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getNowConnection() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取服务
|
|
|
- * Get service
|
|
|
- * @return TC_EpollServer*
|
|
|
- */
|
|
|
- TC_EpollServer* getEpollServer() const { return _pEpollServer; };
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取对应的网络线程
|
|
|
- * Get the corresponding network thread
|
|
|
- * @param fd
|
|
|
- * @return
|
|
|
- */
|
|
|
- inline NetThread* getNetThreadOfFd(int fd) const { return _pEpollServer->getNetThreadOfFd(fd); }
|
|
|
-
|
|
|
- /**
|
|
|
- * 注册协议解析器
|
|
|
- * Registration Protocol parser
|
|
|
- * @param pp
|
|
|
- */
|
|
|
- void setProtocol(const TC_NetWorkBuffer::protocol_functor& pf, int iHeaderLen = 0, const header_filter_functor& hf = echo_header_filter);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取协议解析器
|
|
|
- * Get Registration Protocol parser
|
|
|
- * @return protocol_functor&
|
|
|
- */
|
|
|
- TC_NetWorkBuffer::protocol_functor &getProtocol();
|
|
|
-
|
|
|
- /**
|
|
|
- * 解析包头处理对象
|
|
|
- * Resolve Package Header Processing Objects
|
|
|
- * @return protocol_functor&
|
|
|
- */
|
|
|
- header_filter_functor &getHeaderFilterFunctor();
|
|
|
-
|
|
|
- /**
|
|
|
- * 增加数据到队列中
|
|
|
- * Add data to the queue
|
|
|
- * @param vtRecvData
|
|
|
- * @param bPushBack 后端插入
|
|
|
- * @param bPushBack Backend insert
|
|
|
- * @param sBuffer
|
|
|
- */
|
|
|
- void insertRecvQueue(const shared_ptr<RecvContext> &recv);//, bool bPushBack = true);
|
|
|
-
|
|
|
- /**
|
|
|
- * 等待数据
|
|
|
- * Wait for data
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool waitForRecvQueue(uint32_t handleIndex, shared_ptr<RecvContext> &recv);
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收队列的大小
|
|
|
- * Size of the received queue
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- size_t getRecvBufferSize() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送队列的大小
|
|
|
- * Size of the sent queue
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- size_t getSendBufferSize() const;
|
|
|
-
|
|
|
- /**
|
|
|
- * add send buffer size
|
|
|
- */
|
|
|
- inline void increaseSendBufferSize() { ++_iSendBufferSize; }
|
|
|
-
|
|
|
- /**
|
|
|
- * increase send buffer size
|
|
|
- */
|
|
|
- inline void decreaseSendBufferSize(size_t s = 1) { _iSendBufferSize.fetch_sub(s); }
|
|
|
-
|
|
|
- /**
|
|
|
- * 默认的协议解析类, 直接echo
|
|
|
- * Default protocol resolution class, direct echo
|
|
|
- * @param r
|
|
|
- * @param o
|
|
|
- * @return int
|
|
|
- */
|
|
|
- static TC_NetWorkBuffer::PACKET_TYPE echo_protocol(TC_NetWorkBuffer &r, vector<char> &o);
|
|
|
-
|
|
|
- /**
|
|
|
- * 默认的包头处理
|
|
|
- * Default header handling
|
|
|
- * @param i
|
|
|
- * @param o
|
|
|
- * @return int
|
|
|
- */
|
|
|
- static TC_NetWorkBuffer::PACKET_TYPE echo_header_filter(TC_NetWorkBuffer::PACKET_TYPE i, vector<char> &o);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取需要过滤的包头长度
|
|
|
- * Get the header length that needs to be filtered
|
|
|
- */
|
|
|
- int getHeaderFilterLen();
|
|
|
-
|
|
|
- /**
|
|
|
- * 所属handle组的handle数(每个handle一个对象)
|
|
|
- * Number of handles belonging to the handle group (one object per handle)
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getHandleNum();
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化处理线程,线程将会启动
|
|
|
- * Initialize the processing thread, which will start
|
|
|
- */
|
|
|
- template<typename T, typename ...Args>
|
|
|
- void setHandle(size_t n, Args&&... args)
|
|
|
- {
|
|
|
- if(!_handles.empty())
|
|
|
- {
|
|
|
- getEpollServer()->error("[BindAdapter::setHandle] handle is not empty!");
|
|
|
- return;
|
|
|
- }
|
|
|
-
|
|
|
- _iHandleNum = n;
|
|
|
-
|
|
|
- _threadDataQueue.resize(_iHandleNum + 1);
|
|
|
- _threadDataQueue[0] = std::make_shared<BindAdapter::DataQueue>();
|
|
|
-
|
|
|
- if(_pEpollServer->isMergeHandleNetThread())
|
|
|
- {
|
|
|
- _iHandleNum = _pEpollServer->_netThreadNum;
|
|
|
- }
|
|
|
-
|
|
|
- for (int32_t i = 0; i < _iHandleNum ; ++i)
|
|
|
- {
|
|
|
- HandlePtr handle = new T(args...);
|
|
|
-
|
|
|
- handle->setHandleIndex(i);
|
|
|
-
|
|
|
- handle->setEpollServer(this->getEpollServer());
|
|
|
-
|
|
|
- handle->setBindAdapter(this);
|
|
|
-
|
|
|
- _handles.push_back(handle);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取第几个句柄
|
|
|
- * Get the index of the handle
|
|
|
- * @param index
|
|
|
- * @return
|
|
|
- */
|
|
|
- HandlePtr getHandle(size_t index) {
|
|
|
- assert(index <= _iHandleNum);
|
|
|
- assert(getEpollServer()->isMergeHandleNetThread());
|
|
|
- return _handles[index];
|
|
|
- }
|
|
|
-
|
|
|
- /*
|
|
|
- * 设置服务端积压缓存的大小限制(超过大小启用)
|
|
|
- * Set the size limit of the server's backlog cache (exceeding the size enabled)
|
|
|
- */
|
|
|
- void setBackPacketBuffLimit(size_t iLimitSize) { _iBackPacketBuffLimit = iLimitSize; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取服务端回包缓存的大小限制(超过大小启用)
|
|
|
- * Get the size limit of the server-side packet back cache (exceeding the size enabled)
|
|
|
- */
|
|
|
- size_t getBackPacketBuffLimit() const { return _iBackPacketBuffLimit; }
|
|
|
-
|
|
|
- /*
|
|
|
- * 设置服务端5/s最低发送字节
|
|
|
- * Set the Server 5/s Minimum Sending Bytes
|
|
|
- */
|
|
|
- void setBackPacketBuffMin(size_t iMinLimit) { _iBackPacketBuffMin = iMinLimit; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取服务端5/s最低发送字节
|
|
|
- * Get the Server 5/s Minimum Sending Bytes
|
|
|
- */
|
|
|
- size_t getBackPacketBuffMin() const { return _iBackPacketBuffMin; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取服务端接收队列(如果_rnbuffer有多个, 则根据调用者的线程id来hash获取)
|
|
|
- * Get the server receive queue (if there's more than one _rnbuffer, get from the hash based on the caller's thread id)
|
|
|
- *
|
|
|
- */
|
|
|
- recv_queue &getRecvQueue(uint32_t handleIndex);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取handles
|
|
|
- * Get handles
|
|
|
- */
|
|
|
- const vector<HandlePtr> &getHandles() { return _handles; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否是队列模式(默认是False的)
|
|
|
- * Whether it is the queue mode (Defualt false)
|
|
|
- */
|
|
|
- bool isQueueMode() const { return _queueMode; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 开启队列模式(同一个连接的请求, 落在同一个handle处理线程中)
|
|
|
- * Open queue mode (The requests from the same connecion will fall in the same handle processing thread )
|
|
|
- */
|
|
|
- void enableQueueMode() { _queueMode = true; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 等待队列数据
|
|
|
- * Wait for the queue data
|
|
|
- */
|
|
|
- void waitAtQueue(uint32_t handleIndex, uint32_t waitTime);
|
|
|
-
|
|
|
- /**
|
|
|
- * 通知某个具体handle醒过来
|
|
|
- * Notify a specific handle to wake up
|
|
|
- * @param handleIndex
|
|
|
- */
|
|
|
- void notifyHandle(uint32_t handleIndex);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置close回调函数
|
|
|
- * Set close callback function
|
|
|
- */
|
|
|
- void setOnClose(const close_functor& f) { _closeFunc = f; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 注册鉴权包裹函数
|
|
|
- * Regist Authentication Package Function
|
|
|
- * @param apwf
|
|
|
- */
|
|
|
- void setAuthProcessWrapper(const auth_process_wrapper_functor& apwf) { _authWrapper = apwf; }
|
|
|
-
|
|
|
- void setAkSk(const std::string& ak, const std::string& sk) { _accessKey = ak; _secretKey = sk; }
|
|
|
-
|
|
|
- bool checkAkSk(const std::string& ak, const std::string& sk) { return ak == _accessKey && sk == _secretKey; }
|
|
|
-
|
|
|
- std::string getSk(const std::string& ak) const { return (_accessKey == ak) ? _secretKey : ""; }
|
|
|
-
|
|
|
- void setSSLCtx(const shared_ptr<TC_OpenSSL::CTX>& ctx) { _ctx = ctx; }
|
|
|
- shared_ptr<TC_OpenSSL::CTX> getSSLCtx() { return _ctx; };
|
|
|
-
|
|
|
- private:
|
|
|
- /**
|
|
|
- * 获取等待的队列锁
|
|
|
- * Get the waiting queue lock
|
|
|
- * @return
|
|
|
- */
|
|
|
- TC_ThreadLock &getLock(uint32_t handleIndex);
|
|
|
-
|
|
|
- public:
|
|
|
-
|
|
|
- //统计上报的对象
|
|
|
- //Count reporting objects
|
|
|
- PropertyReport * _pReportQueue = NULL;
|
|
|
- PropertyReport * _pReportConRate = NULL;
|
|
|
- PropertyReport * _pReportTimeoutNum = NULL;
|
|
|
-
|
|
|
- protected:
|
|
|
- friend class TC_EpollServer;
|
|
|
-
|
|
|
- /**
|
|
|
- * 加锁
|
|
|
- * Add lock
|
|
|
- */
|
|
|
- mutable std::mutex _mutex;
|
|
|
-
|
|
|
- /**
|
|
|
- * 服务
|
|
|
- * Service
|
|
|
- */
|
|
|
- TC_EpollServer *_pEpollServer = NULL;
|
|
|
-
|
|
|
- /**
|
|
|
- * Adapter所用的HandleGroup
|
|
|
- * the HandleGroup used by Adapter
|
|
|
- */
|
|
|
- vector<HandlePtr> _handles;
|
|
|
-
|
|
|
- /**
|
|
|
- * 协议解析
|
|
|
- * Destruct the protocol
|
|
|
- */
|
|
|
- TC_NetWorkBuffer::protocol_functor _pf;
|
|
|
-
|
|
|
- /**
|
|
|
- * 首个数据包包头过滤
|
|
|
- * First packet header filtering
|
|
|
- */
|
|
|
- header_filter_functor _hf;
|
|
|
-
|
|
|
- /**
|
|
|
- * adapter的名字
|
|
|
- * adapter name
|
|
|
- */
|
|
|
- string _name;
|
|
|
-
|
|
|
- /**
|
|
|
- * 监听fd
|
|
|
- * listen fd
|
|
|
- */
|
|
|
- TC_Socket _s;
|
|
|
-
|
|
|
- /**
|
|
|
- * 绑定的IP
|
|
|
- * binded ip
|
|
|
- */
|
|
|
- TC_Endpoint _ep;
|
|
|
-
|
|
|
- /**
|
|
|
- * 最大连接数
|
|
|
- * the maximum number of connections
|
|
|
- */
|
|
|
- int _iMaxConns;
|
|
|
-
|
|
|
- /**
|
|
|
- * 当前连接数
|
|
|
- * the current number of connections
|
|
|
- */
|
|
|
- std::atomic<int> _iCurConns;
|
|
|
-
|
|
|
- /**
|
|
|
- * Handle个数
|
|
|
- * the number of Handle
|
|
|
- */
|
|
|
- size_t _iHandleNum;
|
|
|
-
|
|
|
- /**
|
|
|
- * 允许的Order
|
|
|
- * the Allowed Order
|
|
|
- */
|
|
|
- volatile EOrder _eOrder;
|
|
|
-
|
|
|
- /**
|
|
|
- * 允许的ip
|
|
|
- * the Allowed IP
|
|
|
- */
|
|
|
- vector<string> _vtAllow;
|
|
|
-
|
|
|
- /**
|
|
|
- * 禁止的ip
|
|
|
- * the Disabled IP
|
|
|
- */
|
|
|
- vector<string> _vtDeny;
|
|
|
-
|
|
|
- /**
|
|
|
- * 每个线程都有自己的队列
|
|
|
- * 0: 给共享队列模式时使用
|
|
|
- * 1~handle个数: 队列模式时使用
|
|
|
- * Every thread has its own queue.
|
|
|
- * 0: Use when sharing queue mode
|
|
|
- * 1~handle count: Use when queue mode
|
|
|
- */
|
|
|
- vector<shared_ptr<DataQueue>> _threadDataQueue;
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收队列数据总个数
|
|
|
- * the total amount of the received queue data
|
|
|
- */
|
|
|
- atomic<size_t> _iRecvBufferSize{0};
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送队列数据总个数
|
|
|
- * the total amount of the sent queue data
|
|
|
- */
|
|
|
- atomic<size_t> _iSendBufferSize{0};
|
|
|
-
|
|
|
- /**
|
|
|
- * 队列最大容量
|
|
|
- * the maximum capacity of the queue
|
|
|
- */
|
|
|
- int _iQueueCapacity;
|
|
|
-
|
|
|
- /**
|
|
|
- * 消息超时时间(从入队列到出队列间隔)(毫秒)
|
|
|
- * Message timeout (from queue entry to queue exit interval) (milliseconds)
|
|
|
- */
|
|
|
- int _iQueueTimeout;
|
|
|
-
|
|
|
- /**
|
|
|
- * 首个数据包包头长度
|
|
|
- * First packet header length
|
|
|
- */
|
|
|
- int _iHeaderLen;
|
|
|
-
|
|
|
- /**
|
|
|
- * 上次心跳发送时间
|
|
|
- * Last heartbeat sent time
|
|
|
- */
|
|
|
- volatile time_t _iHeartBeatTime;
|
|
|
-
|
|
|
- /**
|
|
|
- * 协议名称,缺省为"tars"
|
|
|
- * Protocol name, default is "tars"
|
|
|
- */
|
|
|
- string _protocolName;
|
|
|
-
|
|
|
- /**
|
|
|
- * 回包缓存限制大小
|
|
|
- * Packet Back Cache Limit Size
|
|
|
- */
|
|
|
- size_t _iBackPacketBuffLimit = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * 回包速度最低限制(5/s), 默认1K
|
|
|
- * Minimum Packet Return Speed Limit (5/s), default 1K
|
|
|
- */
|
|
|
- size_t _iBackPacketBuffMin = 1024;
|
|
|
-
|
|
|
- //队列模式
|
|
|
- //Queue Mode
|
|
|
- bool _queueMode = false;
|
|
|
-
|
|
|
- //listen模式
|
|
|
- //Listen Mode
|
|
|
- bool _manualListen = false;
|
|
|
-
|
|
|
- /**
|
|
|
- * 包裹认证函数,不能为空
|
|
|
- * Package authentication function, cannot be empty
|
|
|
- */
|
|
|
- auth_process_wrapper_functor _authWrapper;
|
|
|
-
|
|
|
- /**
|
|
|
- * 该obj的AK SK
|
|
|
- * the AK SK of the object
|
|
|
- */
|
|
|
- std::string _accessKey;
|
|
|
- std::string _secretKey;
|
|
|
-
|
|
|
- /**
|
|
|
- * ssl ctx
|
|
|
- */
|
|
|
- shared_ptr<TC_OpenSSL::CTX> _ctx;
|
|
|
-
|
|
|
- //连接关闭的回调函数
|
|
|
- //Callback function with connection closed
|
|
|
- close_functor _closeFunc;
|
|
|
-
|
|
|
- };
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- // 服务连接管理
|
|
|
- // Service Connection Management
|
|
|
- /**
|
|
|
- * 建立连接的socket信息
|
|
|
- * Socket information for establishing connections
|
|
|
- */
|
|
|
- class Connection
|
|
|
- {
|
|
|
- public:
|
|
|
- enum EnumConnectionType
|
|
|
- {
|
|
|
- EM_TCP = 0,
|
|
|
- EM_UDP = 1,
|
|
|
- };
|
|
|
-
|
|
|
- /**
|
|
|
- * 构造函数
|
|
|
- * Constructor
|
|
|
- * @param lfd
|
|
|
- * @param s
|
|
|
- * @param ip
|
|
|
- * @param port
|
|
|
- */
|
|
|
- Connection(BindAdapter *pBindAdapter, int lfd, int timeout, int fd, const string& ip, uint16_t port);
|
|
|
-
|
|
|
- /**
|
|
|
- * udp连接
|
|
|
- * UDP connection
|
|
|
- * @param fd
|
|
|
- */
|
|
|
- Connection(BindAdapter *pBindAdapter, int fd);
|
|
|
-
|
|
|
- /**
|
|
|
- * 析构函数
|
|
|
- * Destructor
|
|
|
- */
|
|
|
- virtual ~Connection();
|
|
|
-
|
|
|
- /**
|
|
|
- * 链接所属的adapter
|
|
|
- * the adapter of the connection
|
|
|
- */
|
|
|
- BindAdapterPtr& getBindAdapter() { return _pBindAdapter; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化
|
|
|
- * Initialization
|
|
|
- * @param id, 连接的唯一id
|
|
|
- * @param id, the connection unique id
|
|
|
- */
|
|
|
- void init(unsigned int uid) { _uid = uid; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取连接超时时间
|
|
|
- * Get connection timeout
|
|
|
- *
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getTimeout() const { return _timeout; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取线程的惟一id
|
|
|
- * Get thread unique id
|
|
|
- *
|
|
|
- * @return unsigned int
|
|
|
- */
|
|
|
- uint32_t getId() const { return _uid; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取监听fd
|
|
|
- * Get listening id
|
|
|
- *
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getListenfd() const { return _lfd; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 当前连接fd
|
|
|
- * Current connection fd
|
|
|
- *
|
|
|
- * @return int
|
|
|
- */
|
|
|
- int getfd() const { return _sock.getfd(); }
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否有效
|
|
|
- * Whether it is valid
|
|
|
- *
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool isValid() const { return _sock.isValid();}
|
|
|
-
|
|
|
- /**
|
|
|
- * 远程IP
|
|
|
- * Remote IP
|
|
|
- *
|
|
|
- * @return string
|
|
|
- */
|
|
|
- string getIp() const { return _ip; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 远程端口
|
|
|
- * Remote Port
|
|
|
- *
|
|
|
- * @return uint16_t
|
|
|
- */
|
|
|
- uint16_t getPort() const { return _port; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置首个数据包包头需要过滤的字节数
|
|
|
- * Set the number of bytes the first packet header needs to filter
|
|
|
- */
|
|
|
- void setHeaderFilterLen(int iHeaderLen) { _iHeaderLen = iHeaderLen; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置关闭,发送完当前数据就关闭连接
|
|
|
- * Set shutdown to close connection after sending current data
|
|
|
- */
|
|
|
- bool setClose();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取连接类型
|
|
|
- * Get the type of the connection
|
|
|
- */
|
|
|
- EnumConnectionType getType() const { return _enType; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否是空连接
|
|
|
- * Whether there's empty connection.
|
|
|
- */
|
|
|
- bool isEmptyConn() const {return _bEmptyConn;}
|
|
|
-
|
|
|
- /**
|
|
|
- * Init Auth State;
|
|
|
- */
|
|
|
- void tryInitAuthState(int initState);
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收数据buffer
|
|
|
- * Receive data buffer
|
|
|
- */
|
|
|
- TC_NetWorkBuffer &getRecvBuffer() { return _recvBuffer; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送数据buffer
|
|
|
- * Send data buffer
|
|
|
- */
|
|
|
- TC_NetWorkBuffer &getSendBuffer() { return _sendBuffer; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送buffer里面数据
|
|
|
- * Send the data in the bufer
|
|
|
- * @return
|
|
|
- */
|
|
|
- int sendBuffer();
|
|
|
-
|
|
|
- /**
|
|
|
- * 直接发送裸得应答数据,业务层一般不直接使用,仅仅tcp支持
|
|
|
- * send naked response data
|
|
|
- * @param buffer
|
|
|
- * @return int, -1:发送出错, 0:无数据, 1:发送完毕, 2:还有数据
|
|
|
- * @return int, -1: sending error, 0: no data, 1: send completely, 2: data retains
|
|
|
- * @return
|
|
|
- */
|
|
|
- int sendBufferDirect(const std::string& buff);
|
|
|
-
|
|
|
- /**
|
|
|
- * 直接发送裸得应答数据,业务层一般不直接使用,仅仅tcp支持
|
|
|
- * send naked response data
|
|
|
- * @param buffer
|
|
|
- * @return int, -1:发送出错, 0:无数据, 1:发送完毕, 2:还有数据
|
|
|
- * @return int, -1: sending error, 0: no data, 1: send completely, 2: data retains
|
|
|
- * @return
|
|
|
- */
|
|
|
- int sendBufferDirect(const std::vector<char>& buff);
|
|
|
-
|
|
|
- /**
|
|
|
- * 关闭连接
|
|
|
- * Close the connection
|
|
|
- * @param fd
|
|
|
- */
|
|
|
- void close();
|
|
|
-
|
|
|
- friend class NetThread;
|
|
|
-
|
|
|
- protected:
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加发送buffer
|
|
|
- * Add sanding buffer
|
|
|
- * @param buffer
|
|
|
- * @return int, -1:发送出错, 0:无数据, 1:发送完毕, 2:还有数据
|
|
|
- * @return int, -1: sending error, 0: no data, 1: send completely, 2: data retains
|
|
|
- */
|
|
|
- int send(const shared_ptr<SendContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 读取数据
|
|
|
- * Read data
|
|
|
- * @param fd
|
|
|
- * @return int, -1:接收出错, 0:接收不全, 1:接收到一个完整包
|
|
|
- * @return int, -1: received error, 0: not receive completely, 1: receive a complete package
|
|
|
- */
|
|
|
- int recv();
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收TCP
|
|
|
- * Receive TCP
|
|
|
- */
|
|
|
- int recvTcp();
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收Udp
|
|
|
- * Receive UDP
|
|
|
- */
|
|
|
- int recvUdp();
|
|
|
-
|
|
|
- /**
|
|
|
- * 解析协议
|
|
|
- * Destruct protocol
|
|
|
- * @param o
|
|
|
- */
|
|
|
- int parseProtocol(TC_NetWorkBuffer &rbuf);
|
|
|
-
|
|
|
- /**
|
|
|
- * 增加数据到队列中
|
|
|
- * Add data to the queue
|
|
|
- * @param vtRecvData
|
|
|
- */
|
|
|
- void insertRecvQueue(const shared_ptr<RecvContext> &recv);
|
|
|
-
|
|
|
- /**
|
|
|
- * 对于udp方式的连接,分配指定大小的接收缓冲区
|
|
|
- * For udp-mode connections, allocate receive buffers of a specified size
|
|
|
- *@param nSize
|
|
|
- */
|
|
|
- bool setRecvBuffer(size_t nSize=DEFAULT_RECV_BUFFERSIZE);
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否是tcp连接
|
|
|
- * Whether it is TCP connection.
|
|
|
- * @return
|
|
|
- */
|
|
|
- bool isTcp() const { return _lfd != -1; }
|
|
|
-
|
|
|
- public:
|
|
|
- /**
|
|
|
- * 最后刷新时间
|
|
|
- * Last refresh time
|
|
|
- */
|
|
|
- time_t _iLastRefreshTime;
|
|
|
-
|
|
|
- protected:
|
|
|
-
|
|
|
- /**
|
|
|
- * 适配器
|
|
|
- * Adapter
|
|
|
- */
|
|
|
- BindAdapterPtr _pBindAdapter;
|
|
|
-
|
|
|
- /**
|
|
|
- * TC_Socket
|
|
|
- */
|
|
|
- TC_Socket _sock;
|
|
|
-
|
|
|
- /**
|
|
|
- * 连接的唯一编号
|
|
|
- * the unique id of the connection
|
|
|
- */
|
|
|
- volatile uint32_t _uid;
|
|
|
-
|
|
|
- /**
|
|
|
- * 监听的socket
|
|
|
- * Listening socket
|
|
|
- */
|
|
|
- int _lfd;
|
|
|
-
|
|
|
- /**
|
|
|
- * 超时时间
|
|
|
- * Timeout
|
|
|
- */
|
|
|
- int _timeout;
|
|
|
-
|
|
|
- /**
|
|
|
- * ip
|
|
|
- */
|
|
|
- string _ip;
|
|
|
-
|
|
|
- /**
|
|
|
- * 端口
|
|
|
- * Port
|
|
|
- */
|
|
|
- uint16_t _port;
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收数据buffer
|
|
|
- * the buffer to receive data
|
|
|
- */
|
|
|
- TC_NetWorkBuffer _recvBuffer;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送数据buffer
|
|
|
- * the buffer to send data
|
|
|
- */
|
|
|
- TC_NetWorkBuffer _sendBuffer;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送数据
|
|
|
- * Send data
|
|
|
- */
|
|
|
- size_t _sendBufferSize = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查时间
|
|
|
- * Check time
|
|
|
- */
|
|
|
- time_t _lastCheckTime = 0;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送的检查<已经发送数据, 剩余buffer大小>
|
|
|
- * Check Sent <Data Sent, Remaining Buffer Size>
|
|
|
- */
|
|
|
- vector<pair<size_t, size_t>> _checkSend;
|
|
|
-
|
|
|
- /**
|
|
|
- * 需要过滤的头部字节数
|
|
|
- * Number of header bytes to filter
|
|
|
- */
|
|
|
- int _iHeaderLen;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送完当前数据就关闭连接
|
|
|
- * Close connection after sending current data
|
|
|
- */
|
|
|
- bool _bClose;
|
|
|
-
|
|
|
- /**
|
|
|
- * 连接类型
|
|
|
- * Connection Type
|
|
|
- */
|
|
|
- EnumConnectionType _enType;
|
|
|
-
|
|
|
- bool _bEmptyConn;
|
|
|
-
|
|
|
- /*
|
|
|
- *接收数据的临时buffer,加这个目的是对udp接收数据包大小进行设置
|
|
|
- *Temporary buffer to receive data, plus this is to set the UDP receive packet size
|
|
|
- */
|
|
|
- char *_pRecvBuffer = NULL;
|
|
|
-
|
|
|
- size_t _nRecvBufferSize;
|
|
|
-
|
|
|
- public:
|
|
|
- /*
|
|
|
- *该连接的鉴权状态
|
|
|
- *Authentication status of the connection
|
|
|
- */
|
|
|
- int _authState;
|
|
|
- /*
|
|
|
- *该连接的鉴权状态是否初始化了
|
|
|
- */
|
|
|
- bool _authInit;
|
|
|
-
|
|
|
- std::shared_ptr<TC_OpenSSL> _openssl;
|
|
|
- };
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- /**
|
|
|
- * 带有时间链表的map
|
|
|
- * Map with Time Chain Table
|
|
|
- */
|
|
|
- class ConnectionList
|
|
|
- {
|
|
|
- public:
|
|
|
- /**
|
|
|
- * 构造函数
|
|
|
- * Constructor
|
|
|
- */
|
|
|
- ConnectionList(NetThread *pEpollServer);
|
|
|
-
|
|
|
- /**
|
|
|
- * 析够函数
|
|
|
- * Destructor
|
|
|
- */
|
|
|
- ~ConnectionList()
|
|
|
- {
|
|
|
- if(_vConn)
|
|
|
- {
|
|
|
- //服务停止时, 主动关闭一下连接, 这样客户端会检测到, 不需要等下一个发送包时, 发送失败才知道连接被关闭
|
|
|
- for (auto it = _tl.begin(); it != _tl.end(); ++it) {
|
|
|
- if (_vConn[it->second].first != NULL) {
|
|
|
- _vConn[it->second].first->close();
|
|
|
- }
|
|
|
- }
|
|
|
- delete[] _vConn;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化大小
|
|
|
- * Initial size
|
|
|
- * @param size
|
|
|
- */
|
|
|
- void init(uint32_t size, uint32_t iIndex = 0);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取惟一ID
|
|
|
- * Get the unique ID
|
|
|
- *
|
|
|
- * @return unsigned int
|
|
|
- */
|
|
|
- uint32_t getUniqId();
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加连接
|
|
|
- * Add Connection
|
|
|
- * @param cPtr
|
|
|
- * @param iTimeOutStamp
|
|
|
- */
|
|
|
- void add(Connection *cPtr, time_t iTimeOutStamp);
|
|
|
-
|
|
|
- /**
|
|
|
- * 刷新时间链
|
|
|
- * Refresh the connectiom
|
|
|
- * @param uid
|
|
|
- * @param iTimeOutStamp, 超时时间点
|
|
|
- * @param iTimeOutStamp, Timeout Point
|
|
|
- */
|
|
|
- void refresh(uint32_t uid, time_t iTimeOutStamp);
|
|
|
-
|
|
|
- /**
|
|
|
- * 检查超时数据
|
|
|
- * Check Timeout
|
|
|
- */
|
|
|
- void checkTimeout(time_t iCurTime);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取某个监听端口的连接
|
|
|
- * Get a connection to a listening port
|
|
|
- * @param lfd
|
|
|
- * @return vector<TC_EpollServer::ConnStatus>
|
|
|
- */
|
|
|
- vector<ConnStatus> getConnStatus(int lfd);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取某一个连接
|
|
|
- * Get a certain connection
|
|
|
- * @param p
|
|
|
- * @return T
|
|
|
- */
|
|
|
- Connection* get(uint32_t uid);
|
|
|
-
|
|
|
- /**
|
|
|
- * 删除连接
|
|
|
- * Delete connection
|
|
|
- * @param uid
|
|
|
- */
|
|
|
- void del(uint32_t uid);
|
|
|
-
|
|
|
- /**
|
|
|
- * 大小
|
|
|
- * Size
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- size_t size();
|
|
|
-
|
|
|
- protected:
|
|
|
- typedef pair<Connection*, multimap<time_t, uint32_t>::iterator> list_data;
|
|
|
-
|
|
|
- /**
|
|
|
- * 内部删除, 不加锁
|
|
|
- * Internal Delete, No Lock
|
|
|
- * @param uid
|
|
|
- */
|
|
|
- void _del(uint32_t uid);
|
|
|
-
|
|
|
- protected:
|
|
|
- /**
|
|
|
- * 无锁
|
|
|
- * No Lock
|
|
|
- */
|
|
|
- TC_ThreadMutex _mutex;
|
|
|
-
|
|
|
- /**
|
|
|
- * 服务
|
|
|
- * Service
|
|
|
- */
|
|
|
- NetThread *_pEpollServer;
|
|
|
-
|
|
|
- /**
|
|
|
- * 总计连接数
|
|
|
- * Total connection amount
|
|
|
- */
|
|
|
- volatile uint32_t _total;
|
|
|
-
|
|
|
- /**
|
|
|
- * 空闲链表
|
|
|
- * Empty link list
|
|
|
- */
|
|
|
- list<uint32_t> _free;
|
|
|
-
|
|
|
- /**
|
|
|
- * 空闲链元素个数
|
|
|
- * number of the elements in the empty link
|
|
|
- */
|
|
|
- volatile size_t _free_size;
|
|
|
-
|
|
|
- /**
|
|
|
- * 链接
|
|
|
- * Connection
|
|
|
- */
|
|
|
- list_data *_vConn;
|
|
|
-
|
|
|
- /**
|
|
|
- * 超时链表
|
|
|
- * Timeout link list
|
|
|
- */
|
|
|
- multimap<time_t, uint32_t> _tl;
|
|
|
-
|
|
|
- /**
|
|
|
- * 上次检查超时时间
|
|
|
- * Last timeout time
|
|
|
- */
|
|
|
- time_t _lastTimeoutTime;
|
|
|
-
|
|
|
- /**
|
|
|
- * 链接ID的魔数
|
|
|
- * Magic Number of Link IDs
|
|
|
- */
|
|
|
- uint32_t _iConnectionMagic;
|
|
|
- };
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- class NetThread : public TC_Thread, public TC_HandleBase
|
|
|
- {
|
|
|
- public:
|
|
|
-
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
- public:
|
|
|
- /**
|
|
|
- * 构造函数
|
|
|
- * Constructor
|
|
|
- */
|
|
|
- NetThread(TC_EpollServer *epollServer, int index);
|
|
|
-
|
|
|
- /**
|
|
|
- * 析构函数
|
|
|
- * Destructor
|
|
|
- */
|
|
|
- virtual ~NetThread();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取网络线程的index
|
|
|
- * Get the index for the network threads
|
|
|
- * @return
|
|
|
- */
|
|
|
- int getIndex() const { return _threadIndex; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 网络线程执行函数
|
|
|
- * Network thread execution function
|
|
|
- */
|
|
|
- virtual void run();
|
|
|
-
|
|
|
- /**
|
|
|
- * 停止网络线程
|
|
|
- * Stop the network thread
|
|
|
- */
|
|
|
- void terminate();
|
|
|
-
|
|
|
- /**
|
|
|
- * 生成epoll
|
|
|
- * Generate epoll
|
|
|
- */
|
|
|
- void createEpoll(uint32_t maxAllConn);
|
|
|
-
|
|
|
- /**
|
|
|
- * 初始化udp监听
|
|
|
- * Initialize UDP listening
|
|
|
- */
|
|
|
- void initUdp(const unordered_map<int, BindAdapterPtr> &listeners);
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否服务结束了
|
|
|
- * Whether the service is end.
|
|
|
- *
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool isTerminate() const { return _bTerminate; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取Epoller对象
|
|
|
- * Get the Epoller Object
|
|
|
- *
|
|
|
- * @return TC_Epoller*
|
|
|
- */
|
|
|
- TC_Epoller* getEpoller() { return &_epoller; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 唤醒网络线程
|
|
|
- * Wake up the network thread
|
|
|
- */
|
|
|
- void notify();
|
|
|
-
|
|
|
- /**
|
|
|
- * 关闭连接
|
|
|
- * Close Connection
|
|
|
- * @param uid
|
|
|
- */
|
|
|
- void close(const shared_ptr<RecvContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送数据
|
|
|
- * Send data
|
|
|
- * @param uid
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void send(const shared_ptr<SendContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取某一监听端口的连接数
|
|
|
- * Get the number of connections for a listening port
|
|
|
- * @param lfd
|
|
|
- *
|
|
|
- * @return vector<TC_EpollServer::ConnStatus>
|
|
|
- */
|
|
|
- vector<TC_EpollServer::ConnStatus> getConnStatus(int lfd);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取连接数
|
|
|
- * Get the number of connections
|
|
|
- *
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- size_t getConnectionCount() { return _list.size(); }
|
|
|
-
|
|
|
- /**
|
|
|
- * 记录日志
|
|
|
- * Logging
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void debug(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * INFO日志
|
|
|
- * INFO LOG
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void info(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * TARS日志
|
|
|
- * TARS LOG
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void tars(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 记录错误日志
|
|
|
- * Log errors
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void error(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否启用防止空链接攻击的机制
|
|
|
- * Whether the mechanism to prevent null link attacks is enabled.
|
|
|
- * @param bEnable
|
|
|
- */
|
|
|
- void enAntiEmptyConnAttack(bool bEnable);
|
|
|
-
|
|
|
- /**
|
|
|
- *设置空连接超时时间
|
|
|
- *Set empty connection timeout
|
|
|
- */
|
|
|
- void setEmptyConnTimeout(int timeout);
|
|
|
-
|
|
|
- /**
|
|
|
- *设置udp的接收缓存区大小,单位是B,最小值为8192,最大值为DEFAULT_RECV_BUFFERSIZE
|
|
|
- *Sets the size of the receiving buffer in UDP in B, with a minimum of 8192 and a maximum of DEFAULT_RECV_BUFFERSIZE
|
|
|
- */
|
|
|
- void setUdpRecvBufferSize(size_t nSize=DEFAULT_RECV_BUFFERSIZE);
|
|
|
-
|
|
|
-
|
|
|
- protected:
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取连接
|
|
|
- * Get connection
|
|
|
- * @param id
|
|
|
- *
|
|
|
- * @return ConnectionPtr
|
|
|
- */
|
|
|
- Connection *getConnectionPtr(uint32_t uid) { return _list.get(uid); }
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加tcp链接
|
|
|
- * Add TCP connection
|
|
|
- * @param cPtr
|
|
|
- * @param iIndex
|
|
|
- */
|
|
|
- void addTcpConnection(Connection *cPtr);
|
|
|
-
|
|
|
- /**
|
|
|
- * 添加udp连接
|
|
|
- * Add UDP connection
|
|
|
- * @param cPtr
|
|
|
- * @param index
|
|
|
- */
|
|
|
- void addUdpConnection(Connection *cPtr);
|
|
|
-
|
|
|
- /**
|
|
|
- * 删除链接
|
|
|
- * Delete connection
|
|
|
- * @param cPtr
|
|
|
- * @param bEraseList 是否是超时连接的删除
|
|
|
- * @param bEraseList Whether it is deletion of timeout connection
|
|
|
- * @param closeType 关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭
|
|
|
- * @param closeType Close type, 0: indicates active closure of client, 1: active closure of server, 2: active closure of connection timeout server
|
|
|
- */
|
|
|
- void delConnection(Connection *cPtr, bool bEraseList = true, EM_CLOSE_T closeType=EM_CLIENT_CLOSE);
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理管道消息
|
|
|
- * Processing Pipeline Messages
|
|
|
- */
|
|
|
- void processPipe();
|
|
|
-
|
|
|
- /**
|
|
|
- * 处理网络请求
|
|
|
- * Processing Network Request
|
|
|
- */
|
|
|
- void processNet(const epoll_event &ev);
|
|
|
-
|
|
|
- /**
|
|
|
- * 空连接超时时间
|
|
|
- * Empty connection timeout
|
|
|
- */
|
|
|
- int getEmptyConnTimeout() const;
|
|
|
-
|
|
|
- /**
|
|
|
- *是否空连接检测
|
|
|
- *Empty connection detection examination
|
|
|
- */
|
|
|
- bool isEmptyConnCheck() const;
|
|
|
-
|
|
|
- friend class BindAdapter;
|
|
|
- friend class ConnectionList;
|
|
|
- friend class TC_EpollServer;
|
|
|
-
|
|
|
- private:
|
|
|
- /**
|
|
|
- * 服务
|
|
|
- * Service
|
|
|
- */
|
|
|
- TC_EpollServer *_epollServer;
|
|
|
-
|
|
|
- /**
|
|
|
- * net线程的id
|
|
|
- * the net thread id
|
|
|
- */
|
|
|
- std::thread::id _threadId;
|
|
|
-
|
|
|
- /**
|
|
|
- * 线程索引
|
|
|
- * the thread index
|
|
|
- */
|
|
|
- int _threadIndex;
|
|
|
-
|
|
|
- /**
|
|
|
- * epoll
|
|
|
- */
|
|
|
- TC_Epoller _epoller;
|
|
|
-
|
|
|
- /**
|
|
|
- * 停止
|
|
|
- * Stop
|
|
|
- */
|
|
|
- bool _bTerminate;
|
|
|
-
|
|
|
- /**
|
|
|
- * 通知epoll
|
|
|
- * Notify epoll
|
|
|
- */
|
|
|
- TC_Epoller::NotifyInfo _notify;
|
|
|
-
|
|
|
- /**
|
|
|
- * 管理的连接链表
|
|
|
- * Managed Link List
|
|
|
- */
|
|
|
- ConnectionList _list;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送队列
|
|
|
- * Sending Queue
|
|
|
- */
|
|
|
- send_queue _sbuffer;
|
|
|
-
|
|
|
- /**
|
|
|
- *空连接检测机制开关
|
|
|
- *Switch for empty connection detection mechanism
|
|
|
- */
|
|
|
- bool _bEmptyConnAttackCheck;
|
|
|
-
|
|
|
-
|
|
|
- /**
|
|
|
- * 空连接超时时间,单位是毫秒,默认值2s,
|
|
|
- * 该时间必须小于等于adapter自身的超时时间
|
|
|
- * Empty connection timeout in milliseconds, default 2s,
|
|
|
- * The time must be less than or equal to the adapter's own timeout
|
|
|
- */
|
|
|
- int _iEmptyCheckTimeout;
|
|
|
-
|
|
|
- /**
|
|
|
- * udp连接时接收包缓存大小,针对所有udp接收缓存有效
|
|
|
- * Received packet cache size on UDP connection, valid for all UDP receive caches
|
|
|
- */
|
|
|
- size_t _nUdpRecvBufferSize;
|
|
|
-
|
|
|
- /**
|
|
|
- * 通知信号
|
|
|
- * Notification signal
|
|
|
- */
|
|
|
- bool _notifySignal = false;
|
|
|
- };
|
|
|
- ////////////////////////////////////////////////////////////////////////////
|
|
|
-public:
|
|
|
- /**
|
|
|
- * 构造函数
|
|
|
- * Constructor
|
|
|
- */
|
|
|
- TC_EpollServer(unsigned int iNetThreadNum = 1);
|
|
|
-
|
|
|
- /**
|
|
|
- * 析构函数
|
|
|
- * Destructor
|
|
|
- */
|
|
|
- ~TC_EpollServer();
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否启用防止空链接攻击的机制
|
|
|
- * Whether mechanisms to prevent empty link attacks are enabled
|
|
|
- * @param bEnable
|
|
|
- */
|
|
|
- void enAntiEmptyConnAttack(bool bEnable);
|
|
|
-
|
|
|
- /**
|
|
|
- *设置空连接超时时间
|
|
|
- *Set empty connection timeout
|
|
|
- */
|
|
|
- void setEmptyConnTimeout(int timeout);
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置本地日志
|
|
|
- * Set local log
|
|
|
- * @param plocalLogger
|
|
|
- */
|
|
|
- void setLocalLogger(RollWrapperInterface *pLocalLogger) { _pLocalLogger = pLocalLogger; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 选择网络线程
|
|
|
- * Select network threads
|
|
|
- * @param fd
|
|
|
- */
|
|
|
- inline NetThread* getNetThreadOfFd(int fd) { return _netThreads[fd % _netThreads.size()]; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 合并handle线程和网络线程
|
|
|
- * Merge handle and network threads
|
|
|
- * @param merge
|
|
|
- */
|
|
|
- void setMergeHandleNetThread(bool merge) { _mergeHandleNetThread = merge; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否合并handle线程网络线程
|
|
|
- * Whether to merge handle thread network threads
|
|
|
- * @return
|
|
|
- */
|
|
|
- inline bool isMergeHandleNetThread() const { return _mergeHandleNetThread; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 绑定监听socket
|
|
|
- * Bind listening socket
|
|
|
- * @param ls
|
|
|
- */
|
|
|
- int bind(BindAdapterPtr &lsPtr);
|
|
|
-
|
|
|
- /**
|
|
|
- * 启动业务处理线程
|
|
|
- * Start Business Processing Thread
|
|
|
- */
|
|
|
- void startHandle();
|
|
|
-
|
|
|
- /**
|
|
|
- * 生成epoll
|
|
|
- * Generate epoll
|
|
|
- */
|
|
|
- void createEpoll();
|
|
|
-
|
|
|
- /**
|
|
|
- * 运行
|
|
|
- * Run
|
|
|
- */
|
|
|
- void waitForShutdown();
|
|
|
-
|
|
|
- /**
|
|
|
- * 停止服务
|
|
|
- * Stop Service
|
|
|
- */
|
|
|
- void terminate();
|
|
|
-
|
|
|
- /**
|
|
|
- * 是否服务结束了
|
|
|
- * Whether the service is over
|
|
|
- *
|
|
|
- * @return bool
|
|
|
- */
|
|
|
- bool isTerminate() const { return _bTerminate; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 根据名称获取BindAdapter
|
|
|
- * Get BindAdapter according to the name
|
|
|
- * @param sName
|
|
|
- * @return BindAdapterPtr
|
|
|
- */
|
|
|
- BindAdapterPtr getBindAdapter(const string &sName);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取所有adatapters
|
|
|
- * Get all adapters
|
|
|
- * @return
|
|
|
- */
|
|
|
- vector<BindAdapterPtr> getBindAdapters();
|
|
|
-
|
|
|
- /**
|
|
|
- * 向网络线程添加连接
|
|
|
- * Add remote connection to the network thread
|
|
|
- */
|
|
|
- void addConnection(Connection * cPtr, int fd, CONN_TYPE iType);
|
|
|
-
|
|
|
- /**
|
|
|
- * 关闭连接
|
|
|
- * Close connection
|
|
|
- * @param uid
|
|
|
- */
|
|
|
- void close(const shared_ptr<TC_EpollServer::RecvContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送数据
|
|
|
- * Send data
|
|
|
- * @param uid
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void send(const shared_ptr<SendContext> &data);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取某一监听端口的连接数
|
|
|
- * Get the connection amount of a certain listening port
|
|
|
- * @param lfd
|
|
|
- *
|
|
|
- * @return vector<TC_EpollServer::ConnStatus>
|
|
|
- */
|
|
|
- vector<ConnStatus> getConnStatus(int lfd);
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取监听socket信息
|
|
|
- * Get the information of the listening socket
|
|
|
- *
|
|
|
- * @return map<int,ListenSocket>
|
|
|
- */
|
|
|
- unordered_map<int, BindAdapterPtr> getListenSocketInfo();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取所有连接的数目
|
|
|
- * Get the amount of all connections
|
|
|
- *
|
|
|
- * @return size_t
|
|
|
- */
|
|
|
- size_t getConnectionCount();
|
|
|
-
|
|
|
- /**
|
|
|
- * 记录日志
|
|
|
- * Logging
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void debug(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * INFO日志
|
|
|
- * INFO LOG
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void info(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 记录错误日志
|
|
|
- * Log errors
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void error(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * tars日志
|
|
|
- * tars log
|
|
|
- * @param s
|
|
|
- */
|
|
|
- void tars(const string &s) const;
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取网络线程的数目
|
|
|
- * Get the amount of the network threads
|
|
|
- */
|
|
|
- unsigned int getNetThreadNum() { return _netThreadNum; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取网络线程的指针集合
|
|
|
- * Get the collection of pointers for a network thread
|
|
|
- */
|
|
|
- vector<TC_EpollServer::NetThread*> getNetThread() { return _netThreads; }
|
|
|
-
|
|
|
- /**
|
|
|
- * 停止线程
|
|
|
- * Stop the thread
|
|
|
- */
|
|
|
- void stopThread();
|
|
|
-
|
|
|
- /**
|
|
|
- * 获取所有业务线程的数目
|
|
|
- * Get the amount of all the bussiness threads
|
|
|
- */
|
|
|
- size_t getLogicThreadNum();
|
|
|
-
|
|
|
- // 接收新的客户端链接时的回调
|
|
|
- typedef std::function<void (TC_EpollServer::Connection*)> accept_callback_functor;
|
|
|
-
|
|
|
- /*
|
|
|
- * 设置接收链接的回调
|
|
|
- */
|
|
|
- void setOnAccept(const accept_callback_functor& f) { _acceptFunc = f; }
|
|
|
-
|
|
|
- //回调给应用服务
|
|
|
- //Callback to application service
|
|
|
- typedef std::function<void(TC_EpollServer*)> application_callback_functor;
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置waitForShutdown线程回调的心跳
|
|
|
- * Set the heartbeat of the thread callback of the waitForShutdown
|
|
|
- * @param hf [description]
|
|
|
- */
|
|
|
- void setCallbackFunctor(const application_callback_functor &hf) { _hf = hf; }
|
|
|
-
|
|
|
- //网络线程发送心跳的函数
|
|
|
- //Function for network threads to send heartbeats
|
|
|
- typedef std::function<void(const string &)> heartbeat_callback_functor;
|
|
|
-
|
|
|
- /**
|
|
|
- * 设置netthread网络线程发送心跳的函数
|
|
|
- * Function for setting netthreaded network threads to send heartbeats
|
|
|
- * @param hf [description]
|
|
|
- */
|
|
|
- void setHeartBeatFunctor(const heartbeat_callback_functor& heartFunc) { _heartFunc = heartFunc; }
|
|
|
- heartbeat_callback_functor& getHeartBeatFunctor() { return _heartFunc; }
|
|
|
-
|
|
|
-protected:
|
|
|
-
|
|
|
- friend class BindAdapter;
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收句柄
|
|
|
- * Receiving handle
|
|
|
- * @param fd
|
|
|
- * @return
|
|
|
- */
|
|
|
- bool accept(int fd, int domain = AF_INET);
|
|
|
-
|
|
|
- /**
|
|
|
- * 绑定端口
|
|
|
- * Bind Port
|
|
|
- * @param ep
|
|
|
- * @param s
|
|
|
- * @param manualListen
|
|
|
- */
|
|
|
- void bind(const TC_Endpoint &ep, TC_Socket &s, bool manualListen);
|
|
|
-
|
|
|
- static void applicationCallback(TC_EpollServer *epollServer);
|
|
|
-private:
|
|
|
- /**
|
|
|
- * 网络线程
|
|
|
- * Network Thread
|
|
|
- */
|
|
|
- std::vector<NetThread*> _netThreads;
|
|
|
-
|
|
|
- /*
|
|
|
- * 网络线程数目
|
|
|
- * Network Thread Amount
|
|
|
- */
|
|
|
- unsigned int _netThreadNum;
|
|
|
-
|
|
|
- /**
|
|
|
- * epoll
|
|
|
- */
|
|
|
- TC_Epoller _epoller;
|
|
|
-
|
|
|
- /**
|
|
|
- * 通知epoll
|
|
|
- * Notify epoll
|
|
|
- */
|
|
|
- TC_Epoller::NotifyInfo _notify;
|
|
|
-
|
|
|
- /*
|
|
|
- * 服务是否停止
|
|
|
- * Whether the service is stopped
|
|
|
- */
|
|
|
- bool _bTerminate;
|
|
|
-
|
|
|
- /*
|
|
|
- * 业务线程是否启动
|
|
|
- * Whether the bussiness thread is started.
|
|
|
- */
|
|
|
- bool _handleStarted;
|
|
|
-
|
|
|
- /**
|
|
|
- * 合并网络和业务线程
|
|
|
- * Merge network and business threads
|
|
|
- */
|
|
|
- bool _mergeHandleNetThread = false;
|
|
|
-
|
|
|
- /**
|
|
|
- * 本地循环日志
|
|
|
- * Local Loop Log
|
|
|
- */
|
|
|
- RollWrapperInterface *_pLocalLogger;
|
|
|
-
|
|
|
- /**
|
|
|
- *
|
|
|
- */
|
|
|
- vector<BindAdapterPtr> _bindAdapters;
|
|
|
-
|
|
|
- /**
|
|
|
- * 监听socket
|
|
|
- * Listening socket
|
|
|
- */
|
|
|
- unordered_map<int, BindAdapterPtr> _listeners;
|
|
|
-
|
|
|
- /**
|
|
|
- * 应用回调
|
|
|
- * Application callback
|
|
|
- */
|
|
|
- application_callback_functor _hf;
|
|
|
-
|
|
|
- /**
|
|
|
- * 发送心跳的函数
|
|
|
- * Heartbeat Sending Function
|
|
|
- */
|
|
|
- heartbeat_callback_functor _heartFunc;
|
|
|
-
|
|
|
- /**
|
|
|
- * 接收链接的回调函数
|
|
|
- */
|
|
|
- accept_callback_functor _acceptFunc;
|
|
|
-};
|
|
|
-
|
|
|
-typedef TC_AutoPtr<TC_EpollServer> TC_EpollServerPtr;
|
|
|
-
|
|
|
-}
|
|
|
-
|
|
|
-#endif
|
|
|
+/**
|
|
|
+ * Tencent is pleased to support the open source community by making Tars available.
|
|
|
+ *
|
|
|
+ * Copyright (C) 2016THL A29 Limited, a Tencent company. All rights reserved.
|
|
|
+ *
|
|
|
+ * Licensed under the BSD 3-Clause License (the "License"); you may not use this file except
|
|
|
+ * in compliance with the License. You may obtain a copy of the License at
|
|
|
+ *
|
|
|
+ * https://opensource.org/licenses/BSD-3-Clause
|
|
|
+ *
|
|
|
+ * Unless required by applicable law or agreed to in writing, software distributed
|
|
|
+ * under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
|
|
|
+ * CONDITIONS OF ANY KIND, either express or implied. See the License for the
|
|
|
+ * specific language governing permissions and limitations under the License.
|
|
|
+ */
|
|
|
+
|
|
|
+#pragma once
|
|
|
+
|
|
|
+#include <string>
|
|
|
+#include <memory>
|
|
|
+#include <map>
|
|
|
+#include <unordered_map>
|
|
|
+#include <vector>
|
|
|
+#include <list>
|
|
|
+#include <algorithm>
|
|
|
+#include <functional>
|
|
|
+#include "util/tc_epoller.h"
|
|
|
+#include "util/tc_thread.h"
|
|
|
+#include "util/tc_clientsocket.h"
|
|
|
+#include "util/tc_logger.h"
|
|
|
+#include "util/tc_thread_pool.h"
|
|
|
+#include "util/tc_common.h"
|
|
|
+#include "util/tc_network_buffer.h"
|
|
|
+#include "util/tc_transceiver.h"
|
|
|
+#include "util/tc_cas_queue.h"
|
|
|
+#include "util/tc_coroutine.h"
|
|
|
+#include "util/tc_openssl.h"
|
|
|
+
|
|
|
+using namespace std;
|
|
|
+
|
|
|
+/**
|
|
|
+ * 服务模型说明:
|
|
|
+ * - 服务模型全面支持协程化, 一共有四种模式, 可以通过setOpenCoroutine来设置, 这四种模式是:
|
|
|
+ * 1 NET_THREAD_QUEUE_HANDLES_THREAD: 独立网路线程 + 独立handle线程: 网络线程负责收发包, 通过队列唤醒handle线程中处理
|
|
|
+ * 2 NET_THREAD_QUEUE_HANDLES_CO: 独立网路线程组 + 独立handle线程: 网络线程负责收发包, 通过队列唤醒handle线程中处理, handle线程中启动协程处理
|
|
|
+ * 3 NET_THREAD_MERGE_HANDLES_THREAD: 合并网路线程 + handle线程(线程个数以处理线程配置为准, 网络线程配置无效): 连接分配到不同线程中处理(如果是UDP, 则网络线程竞争接收包), 这种模式下延时最小, 相当于每个包的收发以及业务处理都在一个线程中
|
|
|
+ * 4 NET_THREAD_MERGE_HANDLES_CO: 合并网路线程 + handle线程(线程个数以处理线程配置为准, 网络线程配置无效): 连接分配到不同线程中处理(如果是UDP, 则网络线程竞争接收包), 每个包会启动协程来处理
|
|
|
+ *
|
|
|
+ * 设计说明:
|
|
|
+ * - 设计上支持协程化, 这样所有服务端处理请求的线程, 其实本质上都在协程中, 协程的调度背后使用的epoller, 参考tc_coroutine的说明
|
|
|
+ * - 结合到客户端rpc调用, 服务端处理过程中如果发起对另外一个服务的rpc, 这时rpc作为客户端能复用服务处理线程中的epoller, 从而使得客户端和服务端在同一个epoller中使用协程调度
|
|
|
+ * - 这样设计的优势是无论是rpc同步调用还是异步调用, 都在一个线程中执行, 减少了线程的切换, 同时大幅度减少了请求的延时!
|
|
|
+ *
|
|
|
+ * 队列说明:
|
|
|
+ * - 网络线程和业务逻辑线程之间, 存在队列DataQueue
|
|
|
+ * - 这些DataQueue都封装在DataBuffer类中
|
|
|
+ * - DataBuffer对象被BindAdapter以及处理类(Handle)所持有, 即每个BindAdapter会初始化一个DataBuffer并设置给相关的Handle
|
|
|
+ * - 不同服务模型下以及设置了队列模式下, 队列的使用是不同的
|
|
|
+ * 缺省, 非队列模式(enableQueueMode: false)
|
|
|
+ * 1 NET_THREAD_QUEUE_HANDLES_THREAD
|
|
|
+ * - DataBuffer中实际使用的DataQueue就一个, 多个Handle线程竞争该DataQueue, 以获取数据
|
|
|
+ * - 多个handle线程都会等待在队列上
|
|
|
+ * - 网络线程接收到数据后, 会唤醒等待在队列上handle线程
|
|
|
+ * 2 NET_THREAD_QUEUE_HANDLES_CO
|
|
|
+ * - DataBuffer中实际使用的DataQueue就一个, 多个Handle协程竞争该DataQueue, 以获取数据
|
|
|
+ * - 注意: handle线程(协程)都并不会等待在队列上, 而是通过协程调度, 如果没有数据, 协程调度阻塞
|
|
|
+ * - 网络线程接收数据后, 会通过协程调度器唤醒协程
|
|
|
+ * 3 NET_THREAD_MERGE_HANDLES_THREAD
|
|
|
+ * - 网络和handle都在同一个线程中, 但是都以协程模式在运行, 注意: handle协程并不是一个请求一个协程
|
|
|
+ * - 此时DataBuffer中实际使用的DataQueue和Handle是一对一的
|
|
|
+ * - Handle本质运行在协程中, 但是不会每个请求都创建一个协程来执行, 而是连续执行一定的请求后, 会yield释放协程, 让网络线程继续
|
|
|
+ * - Handle协程不会阻塞在队列上, 而是通过协程调度器来唤醒
|
|
|
+ * - 网络线程接收数据后, 会通过协程调度器唤醒协程
|
|
|
+ * 4 NET_THREAD_MERGE_HANDLES_CO
|
|
|
+ * - 网络和handle都在同一个线程中, 但是都以协程模式在运行, 注意: handle协程一个请求创建一个协程
|
|
|
+ * - 此时DataBuffer中实际使用的DataQueue和Handle是一对一的
|
|
|
+ * - Handle协程不会阻塞在队列上, 而是通过协程调度器来唤醒
|
|
|
+ * - 网络线程接收数据后, 会通过协程调度器唤醒协程
|
|
|
+ *
|
|
|
+ * 在队列模式下, 一个连接上来的请求都在同一个handle线程中处理!
|
|
|
+ */
|
|
|
+namespace tars
|
|
|
+{
|
|
|
+class PropertyReport;
|
|
|
+
|
|
|
+namespace detail
|
|
|
+{
|
|
|
+ /**
|
|
|
+ * log接口
|
|
|
+ */
|
|
|
+ class LogInterface
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ virtual ~LogInterface() {}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void debug(const string &s) const = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * INFO日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void info(const string &s) const = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * taf日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void tars(const string &s) const = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录错误日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void error(const string &s) const = 0;
|
|
|
+
|
|
|
+ };
|
|
|
+}
|
|
|
+
|
|
|
+struct TC_EpollServer_Exception : public TC_Exception
|
|
|
+{
|
|
|
+ TC_EpollServer_Exception(const string &buffer) : TC_Exception(buffer) {};
|
|
|
+ ~TC_EpollServer_Exception() {};
|
|
|
+};
|
|
|
+
|
|
|
+class TC_EpollServer : public TC_HandleBase, public detail::LogInterface
|
|
|
+{
|
|
|
+public:
|
|
|
+
|
|
|
+ enum EM_CLOSE_T
|
|
|
+ {
|
|
|
+ EM_CLIENT_CLOSE = 0, //客户端主动关闭
|
|
|
+ EM_SERVER_CLOSE = 1, //服务端业务主动调用close关闭连接,或者框架因某种异常主动关闭连接
|
|
|
+ EM_SERVER_TIMEOUT_CLOSE = 2 //连接超时了,服务端主动关闭
|
|
|
+ };
|
|
|
+
|
|
|
+ enum
|
|
|
+ {
|
|
|
+ MIN_EMPTY_CONN_TIMEOUT = 5 * 1000, /*空链接超时时间(ms)*/
|
|
|
+ DEFAULT_RECV_BUFFERSIZE = 64 * 1024 /*缺省数据接收buffer的大小*/
|
|
|
+ };
|
|
|
+
|
|
|
+ //定义加入到网络线程的fd类别
|
|
|
+ enum CONN_TYPE
|
|
|
+ {
|
|
|
+ TCP_CONNECTION = 0,
|
|
|
+ UDP_CONNECTION = 1,
|
|
|
+ };
|
|
|
+
|
|
|
+ class RecvContext;
|
|
|
+ class SendContext;
|
|
|
+ class NetThread;
|
|
|
+ class ConnectionList;
|
|
|
+ class Connection;
|
|
|
+ class BindAdapter;
|
|
|
+ class Handle;
|
|
|
+
|
|
|
+ typedef shared_ptr<BindAdapter> BindAdapterPtr;
|
|
|
+ typedef shared_ptr<Handle> HandlePtr;
|
|
|
+
|
|
|
+ // typedef TC_AutoPtr<BindAdapter> BindAdapterPtr;
|
|
|
+ // typedef TC_AutoPtr<Handle> HandlePtr;
|
|
|
+
|
|
|
+// using close_functor = std::function<void(void *, EM_CLOSE_T)>;
|
|
|
+ using header_filter_functor = std::function<TC_NetWorkBuffer::PACKET_TYPE(TC_NetWorkBuffer::PACKET_TYPE, vector<char> &)> ;
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+ /**
|
|
|
+ * 接收包的上下文
|
|
|
+ */
|
|
|
+ class RecvContext : public std::enable_shared_from_this<RecvContext>
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ RecvContext(int threadIndex, uint32_t uid,
|
|
|
+ const TC_Socket::addr_type &addr,
|
|
|
+ int fd,
|
|
|
+ const BindAdapterPtr & adapter,
|
|
|
+ bool isClosed = false,
|
|
|
+ int closeType = EM_CLIENT_CLOSE)
|
|
|
+ : _threadIndex(threadIndex)
|
|
|
+ , _uid(uid)
|
|
|
+ , _addr(addr)
|
|
|
+ , _fd(fd)
|
|
|
+ , _adapter(adapter)
|
|
|
+ , _isClosed(isClosed)
|
|
|
+ , _closeType(closeType)
|
|
|
+ , _recvTimeStamp(TNOWMS)
|
|
|
+ {}
|
|
|
+ inline int threadIndex() const { return _threadIndex; }
|
|
|
+ inline uint32_t uid() const { return _uid; }
|
|
|
+ inline const TC_Socket::addr_type& addr() const { return _addr; }
|
|
|
+ inline const string & ip() const { parseIpPort(); return _ip; }
|
|
|
+ inline uint16_t port() const { parseIpPort(); return _port; }
|
|
|
+ inline vector<char> & buffer() { return _rbuffer; }
|
|
|
+ inline const vector<char> & buffer() const { return _rbuffer; }
|
|
|
+ inline int64_t recvTimeStamp() const { return _recvTimeStamp; }
|
|
|
+ inline bool isOverload() const { return _isOverload; }
|
|
|
+ inline void setOverload() { _isOverload = true; }
|
|
|
+ inline bool isClosed() const { return _isClosed; }
|
|
|
+ inline int fd() const { return _fd; }
|
|
|
+ //连接是否还存在(客户端已经关闭)
|
|
|
+ bool connectionExists() const
|
|
|
+ {
|
|
|
+ auto adapter = _adapter.lock();
|
|
|
+ if (adapter)
|
|
|
+ {
|
|
|
+ Connection *cPtr = adapter->getNetThread(_threadIndex)->getConnectionPtr(_uid);
|
|
|
+ return cPtr != NULL;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ // { Connection *cPtr = _adapter->getNetThread(_threadIndex)->getConnectionPtr(_uid); return cPtr != NULL; }
|
|
|
+ inline BindAdapterPtr adapter() { return _adapter.lock(); }
|
|
|
+ inline int closeType() const { return _closeType; }
|
|
|
+ inline void setCloseType(int closeType) { _closeType = closeType; }
|
|
|
+ inline shared_ptr<SendContext> createSendContext() { return std::make_shared<SendContext>(shared_from_this(), 's'); }
|
|
|
+ inline shared_ptr<SendContext> createCloseContext() { return std::make_shared<SendContext>(shared_from_this(), 'c'); }
|
|
|
+ protected:
|
|
|
+ void parseIpPort() const;
|
|
|
+ protected:
|
|
|
+ int _threadIndex; //网络线程id
|
|
|
+ uint32_t _uid; /**连接标示*/
|
|
|
+ TC_Socket::addr_type _addr;
|
|
|
+ mutable string _ip; /**远程连接的ip*/
|
|
|
+ mutable uint16_t _port; /**远程连接的端口*/
|
|
|
+ int _fd; /*保存产生该消息的fd,用于回包时选择网络线程*/
|
|
|
+ weak_ptr<BindAdapter> _adapter; /**标识哪一个adapter的消息*/
|
|
|
+ vector<char> _rbuffer; /**接收的内容*/
|
|
|
+ bool _isOverload = false; /**是否已过载 */
|
|
|
+ bool _isClosed = false; /**是否已关闭*/
|
|
|
+ int _closeType; /*如果是关闭消息包,则标识关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭*/
|
|
|
+ int64_t _recvTimeStamp; /**接收到数据的时间*/
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送包的上下文
|
|
|
+ * 由RecvContext创建出来
|
|
|
+ */
|
|
|
+ class SendContext
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ SendContext(const shared_ptr<RecvContext> & context, char cmd)
|
|
|
+ : _context(context), _cmd(cmd)
|
|
|
+ {
|
|
|
+ _sbuffer = std::make_shared<TC_NetWorkBuffer::Buffer>();
|
|
|
+ }
|
|
|
+
|
|
|
+ inline const shared_ptr<RecvContext> & getRecvContext() { return _context; }
|
|
|
+ inline void setBuffer(const shared_ptr<TC_NetWorkBuffer::Buffer>& buff) { _sbuffer = buff; }
|
|
|
+ inline const shared_ptr<TC_NetWorkBuffer::Buffer> & buffer() { return _sbuffer; }
|
|
|
+ inline char cmd() const { return _cmd; }
|
|
|
+ inline uint32_t uid() const { return _context->uid(); }
|
|
|
+ inline int fd() const { return _context->fd(); }
|
|
|
+ inline const string & ip() const { return _context->ip(); }
|
|
|
+ inline uint16_t port() const { return _context->port(); }
|
|
|
+
|
|
|
+ friend class RecvContext;
|
|
|
+
|
|
|
+ protected:
|
|
|
+ shared_ptr<RecvContext> _context;
|
|
|
+ char _cmd; /**send包才有效, 命令:'c',关闭fd; 's',有数据需要发送*/
|
|
|
+ shared_ptr<TC_NetWorkBuffer::Buffer> _sbuffer; /**发送的内容*/
|
|
|
+ };
|
|
|
+
|
|
|
+// typedef TC_CasQueue<shared_ptr<RecvContext>> recv_queue;
|
|
|
+ typedef TC_ThreadQueue<shared_ptr<RecvContext>> recv_queue;
|
|
|
+// typedef TC_CasQueue<shared_ptr<SendContext>> send_queue;
|
|
|
+ typedef TC_ThreadQueue<shared_ptr<SendContext>> send_queue;
|
|
|
+
|
|
|
+// typedef recv_queue::queue_type recv_queue_type;
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数据队列包装
|
|
|
+ */
|
|
|
+ class DataBuffer
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 数据队列
|
|
|
+ */
|
|
|
+ class DataQueue
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 通知等待在队列上线程都醒过来
|
|
|
+ */
|
|
|
+ inline void notify() { return _rbuffer.notifyT(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * push数据到队列中, 同时唤醒某个等待处理线程
|
|
|
+ * @param recv
|
|
|
+ */
|
|
|
+ inline void push_back(const shared_ptr<RecvContext> &recv ) { _rbuffer.push_back(recv); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 在队列上等待
|
|
|
+ * @param millseconds
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool wait(size_t millseconds) { return _rbuffer.wait(millseconds); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 弹出头部数据(如果没有数据也不阻塞)
|
|
|
+ * @param data
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool pop_front(shared_ptr<RecvContext> &data) { return _rbuffer.pop_front(data, 0, false); }
|
|
|
+
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * 接收的数据队列
|
|
|
+ */
|
|
|
+ recv_queue _rbuffer;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造, 传入handle处理线程,
|
|
|
+ * @param handleNum
|
|
|
+ */
|
|
|
+ DataBuffer(int handleNum);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知唤醒
|
|
|
+ * @param handleIndex
|
|
|
+ */
|
|
|
+ void notifyBuffer(uint32_t handleIndex);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 插入队列
|
|
|
+ * @param recv
|
|
|
+ */
|
|
|
+ void insertRecvQueue(const shared_ptr<RecvContext> &recv);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 等待在队列上
|
|
|
+ * @param handleIndex
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ bool wait(uint32_t handleIndex);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 弹出数据
|
|
|
+ * @param handleIndex
|
|
|
+ * @param data
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ bool pop(uint32_t handleIndex, shared_ptr<RecvContext> &data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否开启队列模式
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool isQueueMode() const { return _queueMode; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 启用队列模式
|
|
|
+ */
|
|
|
+ inline void enableQueueMode() { _queueMode = true; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收buffer的大小
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline size_t getRecvBufferSize() const { return _iRecvBufferSize; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程注册到DataBuffer中
|
|
|
+ * @param handleIndex
|
|
|
+ * @param scheduler
|
|
|
+ */
|
|
|
+ void registerScheduler(uint32_t handleIndex, const shared_ptr<TC_CoroutineScheduler> & scheduler);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程反注册
|
|
|
+ * @param handleIndex
|
|
|
+ */
|
|
|
+ void unregisterScheduler(uint32_t handleIndex);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取handle对应的协程
|
|
|
+ * @param handleIndex
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ const shared_ptr<TC_CoroutineScheduler> &getScheduler(uint32_t handleIndex);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置等待时间
|
|
|
+ * @param iWaitTime
|
|
|
+ */
|
|
|
+ inline void setWaitTime(uint32_t iWaitTime) { _iWaitTime = iWaitTime; }
|
|
|
+
|
|
|
+ protected:
|
|
|
+
|
|
|
+ inline int index(uint32_t handleIndex) { return handleIndex % _threadDataQueue.size(); }
|
|
|
+
|
|
|
+ const shared_ptr<DataQueue> &getDataQueue(uint32_t handleIndex);
|
|
|
+
|
|
|
+ protected:
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收队列数据总个数
|
|
|
+ */
|
|
|
+ atomic<size_t> _iRecvBufferSize {0};
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否启用队列模式, 相同连接固定
|
|
|
+ */
|
|
|
+ bool _queueMode = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每个线程都有自己的队列
|
|
|
+ * 0: 给共享队列模式时使用
|
|
|
+ * 1~handle个数: 队列模式时使用
|
|
|
+ */
|
|
|
+ vector<shared_ptr<DataQueue>> _threadDataQueue;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * NET_THREAD_AND_HANDLES_CO 模式下有效
|
|
|
+ */
|
|
|
+ vector<shared_ptr<TC_CoroutineScheduler>> _schedulers;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * wait time for queue
|
|
|
+ */
|
|
|
+ int64_t _iWaitTime = 10000;
|
|
|
+ };
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 链接状态
|
|
|
+ */
|
|
|
+ struct ConnStatus
|
|
|
+ {
|
|
|
+ string ip;
|
|
|
+ int32_t uid;
|
|
|
+ uint16_t port;
|
|
|
+ int timeout;
|
|
|
+ int iLastRefreshTime;
|
|
|
+ size_t recvBufferSize;
|
|
|
+ size_t sendBufferSize;
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+ // 服务连接管理
|
|
|
+ /**
|
|
|
+ * 建立连接的socket信息
|
|
|
+ */
|
|
|
+ class Connection
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ * @param lfd
|
|
|
+ * @param s
|
|
|
+ * @param ip
|
|
|
+ * @param port
|
|
|
+ */
|
|
|
+ Connection(const shared_ptr<ConnectionList> &connlist, BindAdapter *pBindAdapter,
|
|
|
+ int fd,
|
|
|
+ const string & ip,
|
|
|
+ uint16_t port,
|
|
|
+ detail::LogInterface *logger);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * udp连接
|
|
|
+ * @param fd
|
|
|
+ */
|
|
|
+ Connection(const shared_ptr<ConnectionList> &connlist, BindAdapter *pBindAdapter, int fd, detail::LogInterface *logger);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 析构函数
|
|
|
+ */
|
|
|
+ virtual ~Connection();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化
|
|
|
+ * @param id, 连接的唯一id
|
|
|
+ */
|
|
|
+ void initialize(TC_Epoller *epoller, unsigned int uid, NetThread *netThread);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取关联的网络线程
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline NetThread *getNetThread() { return _netThread; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 链接所属的adapter
|
|
|
+ */
|
|
|
+ inline BindAdapter* getBindAdapter() { return _pBindAdapter; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * registry epoll event
|
|
|
+ */
|
|
|
+ void registerEvent(NetThread *netThread);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * get epoll info
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline const shared_ptr<TC_Epoller::EpollInfo> &getEpollInfo() { return _trans->getEpollInfo(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连接超时时间
|
|
|
+ *
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ inline int getTimeout() const { return this->_pBindAdapter->getEndpoint().getTimeout()/1000; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取线程的惟一id
|
|
|
+ *
|
|
|
+ * @return unsigned int
|
|
|
+ */
|
|
|
+ inline uint32_t getId() const { return _uid; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当前连接fd
|
|
|
+ *
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ inline int getfd() const { return _trans->fd(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否有效
|
|
|
+ *
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ inline bool isValid() const { return _trans->isValid(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 远程IP
|
|
|
+ *
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ inline const string &getIp() const { return _ip; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 远程端口
|
|
|
+ *
|
|
|
+ * @return uint16_t
|
|
|
+ */
|
|
|
+ inline uint16_t getPort() const { return _port; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置首个数据包包头需要过滤的字节数
|
|
|
+ */
|
|
|
+ inline void setHeaderFilterLen(int iHeaderLen) { _iHeaderLen = iHeaderLen; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置关闭,发送完当前数据就关闭连接
|
|
|
+ */
|
|
|
+ bool setClose();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否是空连接
|
|
|
+ */
|
|
|
+ inline bool isEmptyConn() const { return _bEmptyConn; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连接
|
|
|
+ */
|
|
|
+ inline TC_Transceiver* getTransceiver() { return _trans.get(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收数据buffer
|
|
|
+ */
|
|
|
+ inline TC_NetWorkBuffer & getRecvBuffer() { return _trans->getRecvBuffer(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送数据buffer
|
|
|
+ */
|
|
|
+ inline TC_NetWorkBuffer & getSendBuffer() { return _trans->getSendBuffer(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送buffer里面数据
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ int sendBuffer();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 直接发送裸得应答数据,业务层一般不直接使用,仅仅tcp支持
|
|
|
+ * send naked response data
|
|
|
+ * @param buffer
|
|
|
+ * @return int, -1:发送出错, 0:无数据, 1:发送完毕, 2:还有数据
|
|
|
+ * @return int, -1: sending error, 0: no data, 1: send completely, 2: data retains
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ int sendBufferDirect(const std::string& buff);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加发送buffer
|
|
|
+ * @param buffer
|
|
|
+ * @return int, -1:发送出错, 0:无数据, 1:发送完毕, 2:还有数据
|
|
|
+ */
|
|
|
+ int send(const shared_ptr<SendContext> & data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 增加数据到队列中
|
|
|
+ * @param vtRecvData
|
|
|
+ */
|
|
|
+ inline void insertRecvQueue(const shared_ptr<RecvContext> & recv) { _pBindAdapter->insertRecvQueue(recv); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对于udp方式的连接,分配指定大小的接收缓冲区
|
|
|
+ *@param nSize
|
|
|
+ */
|
|
|
+ void setUdpRecvBuffer(size_t nSize);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否是tcp连接
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool isTcp() const { return _trans->getEndpoint().isTcp(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否是udp连接
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool isUdp() const { return _trans->getEndpoint().isUdp(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭连接
|
|
|
+ */
|
|
|
+ void close();
|
|
|
+
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * 关闭连接
|
|
|
+ * @param fd
|
|
|
+ */
|
|
|
+ void onCloseCallback(TC_Transceiver *trans, TC_Transceiver::CloseReason reason, const string &err);
|
|
|
+
|
|
|
+ void onRequestCallback(TC_Transceiver *trans);
|
|
|
+
|
|
|
+ TC_NetWorkBuffer::PACKET_TYPE onParserCallback(TC_NetWorkBuffer& buff, TC_Transceiver *trans);
|
|
|
+
|
|
|
+ std::shared_ptr<TC_OpenSSL> onOpensslCallback(TC_Transceiver* trans);
|
|
|
+
|
|
|
+ bool handleOutputImp(const shared_ptr<TC_Epoller::EpollInfo> &data);
|
|
|
+ bool handleInputImp(const shared_ptr<TC_Epoller::EpollInfo> &data);
|
|
|
+ bool handleCloseImp(const shared_ptr<TC_Epoller::EpollInfo> &data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查发送流量(避免发送数据量特别大, 而网络很慢, 导致内存不断在扩大, 相当于内存泄露了!)
|
|
|
+ * @param sendBuffer : 当前正在发送的buffer
|
|
|
+ * @param nowLeftBufferSize, 当前剩余还没有发送的数据大小
|
|
|
+ * @return <0, 被限制了, 0: 可以继续发送
|
|
|
+ */
|
|
|
+ int checkFlow(TC_NetWorkBuffer& sendBuffer, size_t nowLeftBufferSize);
|
|
|
+ public:
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 最后刷新时间
|
|
|
+ */
|
|
|
+ time_t _iLastRefreshTime;
|
|
|
+
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * 连接list
|
|
|
+ */
|
|
|
+ weak_ptr<ConnectionList> _connList;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * log interface
|
|
|
+ */
|
|
|
+ detail::LogInterface *_logger = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 适配器
|
|
|
+ */
|
|
|
+ BindAdapter* _pBindAdapter = NULL;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 收发包处理
|
|
|
+ */
|
|
|
+ std::unique_ptr<TC_Transceiver> _trans;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 连接的唯一编号
|
|
|
+ */
|
|
|
+ uint32_t _uid;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * fd socket
|
|
|
+ */
|
|
|
+ int _fd;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * ip
|
|
|
+ */
|
|
|
+ string _ip;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 端口
|
|
|
+ */
|
|
|
+ uint16_t _port;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 还未发送的数据队列
|
|
|
+ */
|
|
|
+ list<shared_ptr<SendContext>> _messages;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * message队列中消息内存大小
|
|
|
+ */
|
|
|
+ size_t _messageSize = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 每5秒发送的数据
|
|
|
+ */
|
|
|
+ size_t _accumulateBufferSize = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查时间
|
|
|
+ */
|
|
|
+ time_t _lastCheckTime = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送的检查<已经发送数据, 剩余buffer大小>
|
|
|
+ */
|
|
|
+ vector<pair<size_t, size_t>> _checkSend;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 需要过滤的头部字节数
|
|
|
+ */
|
|
|
+ int _iHeaderLen;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送完当前数据就关闭连接
|
|
|
+ */
|
|
|
+ bool _bClose;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 即是否是空连接(一个完整包都没有收到过)
|
|
|
+ */
|
|
|
+ bool _bEmptyConn;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 线程的id
|
|
|
+ */
|
|
|
+ NetThread * _netThread = NULL;
|
|
|
+ };
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+ /**
|
|
|
+ * 带有时间链表的map
|
|
|
+ */
|
|
|
+ class ConnectionList
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ */
|
|
|
+ ConnectionList(detail::LogInterface *logger);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 析够函数
|
|
|
+ */
|
|
|
+ ~ConnectionList()
|
|
|
+ {
|
|
|
+ assert(_vConn == NULL);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化大小
|
|
|
+ * @param size
|
|
|
+ */
|
|
|
+ void init(uint32_t size, uint32_t iIndex = 0);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * close所有链接
|
|
|
+ */
|
|
|
+ void close();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭
|
|
|
+ * @param bindFd
|
|
|
+ */
|
|
|
+ void closeConnections(weak_ptr<BindAdapter> bindAdapter);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取惟一ID
|
|
|
+ *
|
|
|
+ * @return unsigned int
|
|
|
+ */
|
|
|
+ uint32_t getUniqId();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加连接
|
|
|
+ * @param cPtr
|
|
|
+ * @param iTimeOutStamp
|
|
|
+ */
|
|
|
+ void add(Connection *cPtr, time_t iTimeOutStamp);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 刷新时间链
|
|
|
+ * @param uid
|
|
|
+ * @param iTimeOutStamp, 超时时间点
|
|
|
+ */
|
|
|
+ void refresh(uint32_t uid, time_t iTimeOutStamp);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除连接
|
|
|
+ * @param cPtr
|
|
|
+ * @param bEraseList
|
|
|
+ * @param closeType
|
|
|
+ */
|
|
|
+ void delConnection(Connection *cPtr, bool bEraseList, EM_CLOSE_T closeType);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置empty conn timeout(ms), 注意精度只能到秒
|
|
|
+ * @param timeout
|
|
|
+ */
|
|
|
+ inline void setEmptyConnTimeout(int timeout) { _emptyCheckTimeout = timeout; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * get empty connection timeout
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline int getEmptyConnTimeout() { return _emptyCheckTimeout; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查超时数据
|
|
|
+ */
|
|
|
+ void checkTimeout();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取某个监听端口的连接
|
|
|
+ * @param lfd
|
|
|
+ * @return vector<TC_EpollServer::ConnStatus>
|
|
|
+ */
|
|
|
+ vector<ConnStatus> getConnStatus(int lfd);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取某一个连接
|
|
|
+ * @param p
|
|
|
+ * @return T
|
|
|
+ */
|
|
|
+ Connection *get(uint32_t uid);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除连接
|
|
|
+ * @param uid
|
|
|
+ */
|
|
|
+ void del(uint32_t uid);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 大小
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline size_t size() { return _total - _free_size; }
|
|
|
+
|
|
|
+ protected:
|
|
|
+ typedef pair<Connection *, multimap<time_t, uint32_t>::iterator> list_data;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 内部删除, 不加锁
|
|
|
+ * @param uid
|
|
|
+ */
|
|
|
+ void delNoLock(uint32_t uid);
|
|
|
+
|
|
|
+ protected:
|
|
|
+
|
|
|
+ /**
|
|
|
+ * empty 连接检查(s)
|
|
|
+ */
|
|
|
+ int _emptyCheckTimeout;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * log interface
|
|
|
+ */
|
|
|
+ detail::LogInterface *_logger = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 锁
|
|
|
+ */
|
|
|
+ TC_ThreadMutex _mutex;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 总计连接数
|
|
|
+ */
|
|
|
+ uint32_t _total;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 空闲链表
|
|
|
+ */
|
|
|
+ list<uint32_t> _free;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 空闲链元素个数
|
|
|
+ */
|
|
|
+ size_t _free_size;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 链接
|
|
|
+ */
|
|
|
+ list_data *_vConn = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 超时链表
|
|
|
+ */
|
|
|
+ multimap<time_t, uint32_t> _tl;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上次检查超时时间
|
|
|
+ */
|
|
|
+ time_t _lastTimeoutTime;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 链接ID的魔数
|
|
|
+ */
|
|
|
+ uint32_t _iConnectionMagic;
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+ // 服务端口管理,监听socket信息
|
|
|
+ class BindAdapter : public enable_shared_from_this<BindAdapter> // : public TC_HandleBase
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 缺省的一些定义
|
|
|
+ */
|
|
|
+ enum
|
|
|
+ {
|
|
|
+ DEFAULT_QUEUE_CAP = 10 * 1024, /**流量*/
|
|
|
+ MIN_QUEUE_TIMEOUT = 3 * 1000, /**队列最小超时时间(ms)*/
|
|
|
+ DEFAULT_MAX_CONN = 1024, /**缺省最大连接数*/
|
|
|
+ DEFAULT_QUEUE_TIMEOUT = 60 * 1000, /**缺省的队列超时时间(ms)*/
|
|
|
+ };
|
|
|
+ /**
|
|
|
+ * 顺序
|
|
|
+ */
|
|
|
+ enum EOrder
|
|
|
+ {
|
|
|
+ ALLOW_DENY,
|
|
|
+ DENY_ALLOW
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 析够函数
|
|
|
+ */
|
|
|
+ ~BindAdapter();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置需要手工监听
|
|
|
+ */
|
|
|
+ void enableManualListen();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否手工监听端口
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool isManualListen() const { return this->_manualListen; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 手工绑定端口
|
|
|
+ */
|
|
|
+ void manualListen();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取消监听
|
|
|
+ */
|
|
|
+ void cancelListen();
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ * @param info
|
|
|
+ */
|
|
|
+ inline void setEpollInfo(const shared_ptr<TC_Epoller::EpollInfo> &info) { _info = info; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * get epoll info
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline shared_ptr<TC_Epoller::EpollInfo> getEpollInfo() { return _info; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取adapter name
|
|
|
+ * @return string
|
|
|
+ */
|
|
|
+ const string &getName() const { return _name; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * set index
|
|
|
+ */
|
|
|
+ void setNetThreads(const vector<NetThread*> &netThreads);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * init udp
|
|
|
+ */
|
|
|
+ void initUdp(NetThread* netThread);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * get index
|
|
|
+ */
|
|
|
+ inline const vector<NetThread*> & getNetThreads() const { return _netThreads;}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取queue capacity
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ inline int getQueueCapacity() const { return _iQueueCapacity; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置queue capacity
|
|
|
+ * @param n
|
|
|
+ */
|
|
|
+ inline void setQueueCapacity(int n) { _iQueueCapacity = n; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置协议名称
|
|
|
+ * @param name
|
|
|
+ */
|
|
|
+ void setProtocolName(const string & name);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取协议名称
|
|
|
+ * @return const string&
|
|
|
+ */
|
|
|
+ const string & getProtocolName();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否taf协议
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ bool isTarsProtocol();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 判断是否需要过载保护
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ int isOverloadorDiscard();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置消息在队列中的超时时间, t为毫秒
|
|
|
+ * (超时时间精度只能是s)
|
|
|
+ * @param t
|
|
|
+ */
|
|
|
+ void setQueueTimeout(int t);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取消息在队列中的超时时间, 毫秒
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ inline int getQueueTimeout() const { return _iQueueTimeout; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取ip
|
|
|
+ * @return const string&
|
|
|
+ */
|
|
|
+ inline const TC_Endpoint & getEndpoint() const { return _ep; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 监听socket
|
|
|
+ * @return TC_Socket
|
|
|
+ */
|
|
|
+ inline TC_Socket & getSocket() { return _s; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置最大连接数
|
|
|
+ * @param iMaxConns
|
|
|
+ */
|
|
|
+ inline void setMaxConns(int iMaxConns) { _iMaxConns = iMaxConns; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取最大连接数
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline size_t getMaxConns() const { return _iMaxConns;}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置HeartBeat时间
|
|
|
+ * @param n
|
|
|
+ */
|
|
|
+ inline void setHeartBeatTime(time_t t) { _iHeartBeatTime = t; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取HeartBeat时间
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline time_t getHeartBeatTime() const { return _iHeartBeatTime; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置allow deny次序
|
|
|
+ * @param eOrder
|
|
|
+ */
|
|
|
+ inline void setOrder(EOrder eOrder) { _eOrder = eOrder; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置允许ip
|
|
|
+ * @param vtAllow
|
|
|
+ */
|
|
|
+ inline void setAllow(const vector<string> & vtAllow) { _vtAllow = vtAllow; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置禁止ip
|
|
|
+ * @param vtDeny
|
|
|
+ */
|
|
|
+ inline void setDeny(const vector<string> & vtDeny) { _vtDeny = vtDeny; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取允许ip
|
|
|
+ * @return vector<string>: ip列表
|
|
|
+ */
|
|
|
+ inline const vector<string> & getAllow() const { return _vtAllow; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取禁止ip
|
|
|
+ * @return vector<string>: ip列表
|
|
|
+ */
|
|
|
+ inline const vector<string> & getDeny() const { return _vtDeny; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取allow deny次序
|
|
|
+ * @return EOrder
|
|
|
+ */
|
|
|
+ inline EOrder getOrder() const { return _eOrder; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否Ip被允许
|
|
|
+ * @param ip
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ bool isIpAllow(const string & ip) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否超过了最大连接数
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ inline bool isLimitMaxConnection() const { return (_iCurConns + 1 > (int)_iMaxConns) || (_iCurConns + 1 > (int)((uint32_t)1 << 22) - 1); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 减少当前连接数
|
|
|
+ */
|
|
|
+ inline void decreaseNowConnection() { --_iCurConns; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 增加当前连接数
|
|
|
+ */
|
|
|
+ inline void increaseNowConnection() { ++_iCurConns; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所有链接状态
|
|
|
+ * @return ConnStatus
|
|
|
+ */
|
|
|
+ inline vector<ConnStatus> getConnStatus() { return _epollServer->getConnStatus(_s.getfd()); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取当前连接数
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ inline int getNowConnection() const { return _iCurConns; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取服务
|
|
|
+ * @return TC_EpollServer*
|
|
|
+ */
|
|
|
+ inline TC_EpollServer *getEpollServer() const { return _epollServer; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取对应的网络线程
|
|
|
+ * @param fd
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline NetThread *getNetThread(size_t threadIndex) const { assert(threadIndex < _netThreads.size()); return _netThreads[threadIndex]; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 注册协议解析器
|
|
|
+ * @param pp
|
|
|
+ */
|
|
|
+ void setProtocol(const TC_NetWorkBuffer::protocol_functor & pf, int iHeaderLen = 0, const header_filter_functor & hf = echo_header_filter);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取协议解析器
|
|
|
+ * @return protocol_functor&
|
|
|
+ */
|
|
|
+ inline TC_NetWorkBuffer::protocol_functor & getProtocol() { return _pf; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 解析包头处理对象
|
|
|
+ * @return protocol_functor&
|
|
|
+ */
|
|
|
+ inline header_filter_functor & getHeaderFilterFunctor() { return _hf; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取数据buffer
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline const shared_ptr<DataBuffer> &getDataBuffer() const { return _dataBuffer; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 增加数据到队列中
|
|
|
+ * @param recv
|
|
|
+ * @param force 强制必须插入(无论是否过载, 比如close事件)
|
|
|
+ */
|
|
|
+ void insertRecvQueue(const shared_ptr<RecvContext> & recv, bool force = false);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收队列的大小
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline size_t getRecvBufferSize() const { return _dataBuffer->getRecvBufferSize(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送队列的大小
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline size_t getSendBufferSize() const { return _iSendBufferSize; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * add send buffer size(个数)
|
|
|
+ */
|
|
|
+ inline void increaseSendBufferSize() { ++_iSendBufferSize; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * increase send buffer size
|
|
|
+ */
|
|
|
+ inline void decreaseSendBufferSize(size_t s = 1) { _iSendBufferSize.fetch_sub(s); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认的协议解析类, 直接echo
|
|
|
+ * @param r
|
|
|
+ * @param o
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ static TC_NetWorkBuffer::PACKET_TYPE echo_protocol(TC_NetWorkBuffer & r, vector<char> & o);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认的包头处理
|
|
|
+ * @param i
|
|
|
+ * @param o
|
|
|
+ * @return int
|
|
|
+ */
|
|
|
+ static TC_NetWorkBuffer::PACKET_TYPE echo_header_filter(TC_NetWorkBuffer::PACKET_TYPE i, vector<char> & o);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取需要过滤的包头长度
|
|
|
+ */
|
|
|
+ inline int getHeaderFilterLen() { return _iHeaderLen; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 所属handle组的handle数(每个handle一个对象)
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline int getHandleNum() { return _iHandleNum; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取第几个句柄
|
|
|
+ * @param index
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ HandlePtr getHandle(size_t index)
|
|
|
+ {
|
|
|
+ assert(index <= _iHandleNum);
|
|
|
+ // assert(getEpollServer()->isMergeHandleNetThread());
|
|
|
+ return _handles[index];
|
|
|
+ }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 设置服务端积压缓存的大小限制(超过大小启用)
|
|
|
+ */
|
|
|
+ inline void setBackPacketBuffLimit(size_t iLimitSize) { _iBackPacketBuffLimit = iLimitSize; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取服务端回包缓存的大小限制(超过大小启用)
|
|
|
+ */
|
|
|
+ inline size_t getBackPacketBuffLimit() const { return _iBackPacketBuffLimit; }
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 设置服务端每5s最低发送字节
|
|
|
+ */
|
|
|
+ inline void setBackPacketBuffMin(size_t iMinLimit) { _iBackPacketBuffMin = iMinLimit; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取服务端5/s最低发送字节
|
|
|
+ */
|
|
|
+ inline size_t getBackPacketBuffMin() const { return _iBackPacketBuffMin; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取handles
|
|
|
+ */
|
|
|
+ inline vector<HandlePtr> & getHandles() { return _handles; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否是队列模式(默认是False的)
|
|
|
+ */
|
|
|
+ inline bool isQueueMode() const { return _dataBuffer->isQueueMode(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 开启队列模式(同一个连接的请求, 落在同一个handle处理线程中)
|
|
|
+ */
|
|
|
+ inline void enableQueueMode() { return _dataBuffer->enableQueueMode(); }
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 设置close回调函数
|
|
|
+// */
|
|
|
+// inline void setOnClose(const close_functor & f) { _closeFunc = f; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置accesskey & secretKey & callback
|
|
|
+ * @param ak
|
|
|
+ * @param sk
|
|
|
+ */
|
|
|
+ inline void setAkSkCallback(const std::string & accesskey, const std::string & secretKey, const TC_Transceiver::onserververifyauth_callback &onverify)
|
|
|
+ {
|
|
|
+ _accessKey = accesskey;
|
|
|
+ _secretKey = secretKey;
|
|
|
+ _onVerifyCallback = onverify;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 检查是否key是否匹配
|
|
|
+ * @param accesskey
|
|
|
+ * @param secretKey
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline bool checkAkSk(const std::string & accesskey, const std::string & secretKey)
|
|
|
+ {
|
|
|
+ return accesskey == _accessKey && secretKey == _secretKey;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据accesskey 获取secretkey, 如果accesskey不等, 则返回空
|
|
|
+ * @param ak
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline std::string getSk(const std::string & accesskey) const
|
|
|
+ {
|
|
|
+ return (_accessKey == accesskey) ? _secretKey : "";
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * set openssl ctx
|
|
|
+ * @param ctx
|
|
|
+ */
|
|
|
+ inline void setSSLCtx(const shared_ptr<TC_OpenSSL::CTX> &ctx) { _ctx = ctx; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * get ssl ctx
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ shared_ptr<TC_OpenSSL::CTX> getSSLCtx() { return _ctx; };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ */
|
|
|
+ BindAdapter(TC_EpollServer *epollServer);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置adapter name
|
|
|
+ * @param name
|
|
|
+ */
|
|
|
+ void setName(const string & name) { _name = name; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置endpoint
|
|
|
+ * @param str
|
|
|
+ */
|
|
|
+ inline void setEndpoint(const string & str) { _ep.parse(str); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否是UDP端口
|
|
|
+ */
|
|
|
+ inline bool isUdp() const { return _ep.isUdp(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化处理线程,线程将会启动
|
|
|
+ */
|
|
|
+ template<typename T, typename ...Args>
|
|
|
+ void setHandle(size_t n, Args&&... args)
|
|
|
+ {
|
|
|
+ if (!_handles.empty()) {
|
|
|
+ getEpollServer()->error("[BindAdapter::setHandle] handle is not empty!");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ _iHandleNum = n;
|
|
|
+
|
|
|
+ _dataBuffer.reset(new DataBuffer(_iHandleNum));
|
|
|
+
|
|
|
+ for (size_t i = 0; i < _iHandleNum; ++i)
|
|
|
+ {
|
|
|
+ HandlePtr handle = std::make_shared<T>(args...);
|
|
|
+
|
|
|
+ handle->setHandleIndex(i);
|
|
|
+
|
|
|
+ handle->setEpollServer(this->getEpollServer());
|
|
|
+
|
|
|
+ handle->setBindAdapter(this);
|
|
|
+
|
|
|
+ _handles.push_back(handle);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * 绑定服务器
|
|
|
+ */
|
|
|
+ void bind();
|
|
|
+
|
|
|
+ friend class TC_EpollServer;
|
|
|
+ public:
|
|
|
+
|
|
|
+ //统计上报的对象
|
|
|
+ PropertyReport *_pReportQueue = NULL;
|
|
|
+ PropertyReport *_pReportConRate = NULL;
|
|
|
+ PropertyReport *_pReportTimeoutNum = NULL;
|
|
|
+
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * epoller指针
|
|
|
+ */
|
|
|
+ TC_EpollServer* _epollServer = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 加锁
|
|
|
+ */
|
|
|
+ mutable std::mutex _mutex;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Adapter所用的HandleGroup
|
|
|
+ */
|
|
|
+ vector<HandlePtr> _handles;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协议解析
|
|
|
+ */
|
|
|
+ TC_NetWorkBuffer::protocol_functor _pf;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 首个数据包包头过滤
|
|
|
+ */
|
|
|
+ header_filter_functor _hf;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * adapter的名字
|
|
|
+ */
|
|
|
+ string _name;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * net threads
|
|
|
+ */
|
|
|
+ vector<NetThread*> _netThreads;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 监听fd
|
|
|
+ */
|
|
|
+ TC_Socket _s;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 绑定的IP
|
|
|
+ */
|
|
|
+ TC_Endpoint _ep;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * epoll info
|
|
|
+ */
|
|
|
+ shared_ptr<TC_Epoller::EpollInfo> _info;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 最大连接数
|
|
|
+ */
|
|
|
+ int _iMaxConns;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 当前连接数
|
|
|
+ */
|
|
|
+ std::atomic<int> _iCurConns;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handle个数
|
|
|
+ */
|
|
|
+ size_t _iHandleNum;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 允许的Order
|
|
|
+ */
|
|
|
+ EOrder _eOrder;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 允许的ip
|
|
|
+ */
|
|
|
+ vector<string> _vtAllow;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 禁止的ip
|
|
|
+ */
|
|
|
+ vector<string> _vtDeny;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送队列数据总个数
|
|
|
+ */
|
|
|
+ atomic<size_t> _iSendBufferSize {0};
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数据buffer
|
|
|
+ */
|
|
|
+ shared_ptr<DataBuffer> _dataBuffer;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 队列最大容量
|
|
|
+ */
|
|
|
+ int _iQueueCapacity;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 消息超时时间(从入队列到出队列间隔)(毫秒)
|
|
|
+ */
|
|
|
+ int _iQueueTimeout;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 首个数据包包头长度
|
|
|
+ */
|
|
|
+ int _iHeaderLen;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 上次心跳发送时间
|
|
|
+ */
|
|
|
+ time_t _iHeartBeatTime;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协议名称,缺省为"tars"
|
|
|
+ */
|
|
|
+ string _protocolName;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回包缓存限制大小
|
|
|
+ */
|
|
|
+ size_t _iBackPacketBuffLimit = 1024*1024;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 回包速度最低限制(5/s), 默认1K
|
|
|
+ */
|
|
|
+ size_t _iBackPacketBuffMin = 1024;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * verify auth callback
|
|
|
+ */
|
|
|
+ TC_Transceiver::onserververifyauth_callback _onVerifyCallback;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 该obj的AK SK
|
|
|
+ */
|
|
|
+ std::string _accessKey;
|
|
|
+ std::string _secretKey;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否手工监听
|
|
|
+ */
|
|
|
+ bool _manualListen = false;
|
|
|
+// /**
|
|
|
+// * 创建一个udp句柄, 用来通知事后listen
|
|
|
+// */
|
|
|
+// TC_Socket _udpNotify;
|
|
|
+//
|
|
|
+// /**
|
|
|
+// * 通知
|
|
|
+// */
|
|
|
+// TC_Epoller::EpollInfo *_notifyInfo = NULL;
|
|
|
+
|
|
|
+ //连接关闭的回调函数
|
|
|
+// close_functor _closeFunc;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * ssl ctx
|
|
|
+ */
|
|
|
+ shared_ptr<TC_OpenSSL::CTX> _ctx;
|
|
|
+ };
|
|
|
+
|
|
|
+ ////////////////////////////////////////////////////////////////////////////
|
|
|
+ class NetThread : public TC_Thread
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ */
|
|
|
+ NetThread(int index, TC_EpollServer *epollServer);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 析构函数
|
|
|
+ */
|
|
|
+ virtual ~NetThread();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取网络线程的index
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline int getIndex() const { return _threadIndex; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * connection list
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline const shared_ptr<ConnectionList> &getConnectionList() const { return _list; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 网络线程执行函数
|
|
|
+ */
|
|
|
+ virtual void run();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 停止网络线程
|
|
|
+ */
|
|
|
+ void terminate();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成epoll
|
|
|
+ */
|
|
|
+ void createEpoll(uint32_t maxAllConn);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 已经启动, 进入网络调度状态
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ bool isReady() const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取Epoller对象
|
|
|
+ * @return TC_Epoller*
|
|
|
+ */
|
|
|
+ inline TC_Epoller *getEpoller() { return _epoller; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置初始化和处理对象
|
|
|
+ * @param initialize
|
|
|
+ * @param handle
|
|
|
+ */
|
|
|
+ void setInitializeHandle(std::function<void()> initialize, std::function<void()> handle);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 唤醒网络线程
|
|
|
+ */
|
|
|
+ inline void notify() { assert(_scheduler); _scheduler->notify(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭连接
|
|
|
+ * @param uid
|
|
|
+ */
|
|
|
+ void close(const shared_ptr<RecvContext> & data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送数据
|
|
|
+ * @param uid
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ void send(const shared_ptr<SendContext> & data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取某一监听端口的连接数
|
|
|
+ * @param lfd
|
|
|
+ *
|
|
|
+ * @return vector<ConnStatus>
|
|
|
+ */
|
|
|
+ inline vector<ConnStatus> getConnStatus(int lfd) { return _list->getConnStatus(lfd); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连接数
|
|
|
+ *
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ inline size_t getConnectionCount() { return _list->size(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *设置空连接超时时间
|
|
|
+ */
|
|
|
+ inline void setEmptyConnTimeout(int timeout) {
|
|
|
+ int emptyCheckTimeout = (timeout >= MIN_EMPTY_CONN_TIMEOUT) ? timeout : MIN_EMPTY_CONN_TIMEOUT;
|
|
|
+
|
|
|
+ _list->setEmptyConnTimeout(emptyCheckTimeout);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *设置udp的接收缓存区大小,单位是B,最小值为8192,最大值为DEFAULT_RECV_BUFFERSIZE
|
|
|
+ */
|
|
|
+ inline void setUdpRecvBufferSize(size_t nSize = DEFAULT_RECV_BUFFERSIZE) {
|
|
|
+ _nUdpRecvBufferSize = (nSize >= 8192 && nSize <= DEFAULT_RECV_BUFFERSIZE) ? nSize : DEFAULT_RECV_BUFFERSIZE;
|
|
|
+ }
|
|
|
+
|
|
|
+ protected:
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取连接
|
|
|
+ * @param id
|
|
|
+ *
|
|
|
+ * @return ConnectionPtr
|
|
|
+ */
|
|
|
+ inline Connection *getConnectionPtr(uint32_t uid) { assert(_list); return _list->get(uid); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加tcp链接
|
|
|
+ * @param cPtr
|
|
|
+ * @param iIndex
|
|
|
+ */
|
|
|
+ void addTcpConnection(Connection *cPtr);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 添加udp连接
|
|
|
+ * @param cPtr
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ void addUdpConnection(Connection *cPtr);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 删除链接
|
|
|
+ * @param cPtr
|
|
|
+ * @param bEraseList 是否是超时连接的删除
|
|
|
+ * @param closeType 关闭类型,0:表示客户端主动关闭;1:服务端主动关闭;2:连接超时服务端主动关闭
|
|
|
+ */
|
|
|
+ void delConnection(Connection *cPtr, bool bEraseList = true, EM_CLOSE_T closeType = EM_CLIENT_CLOSE);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理管道消息
|
|
|
+ */
|
|
|
+ void processPipe();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 空连接超时时间
|
|
|
+ */
|
|
|
+ inline int getEmptyConnTimeout() const { return _list->getEmptyConnTimeout(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ *是否空连接检测
|
|
|
+ */
|
|
|
+ inline bool isEmptyConnCheck() const { return _list->getEmptyConnTimeout() > 0; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关联adapter
|
|
|
+ * @param adapter
|
|
|
+ */
|
|
|
+ inline void addAdapter(BindAdapter* adapter) { _adapters.push_back(adapter); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知关闭连接
|
|
|
+ * @param fd
|
|
|
+ */
|
|
|
+ void notifyCloseConnectionList(const shared_ptr<BindAdapter> &adapter);
|
|
|
+
|
|
|
+ friend class BindAdapter;
|
|
|
+ friend class TC_EpollServer;
|
|
|
+ friend class ConnectionList;
|
|
|
+
|
|
|
+ private:
|
|
|
+
|
|
|
+ /**
|
|
|
+ * scheduler
|
|
|
+ */
|
|
|
+ shared_ptr<TC_CoroutineScheduler> _scheduler;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * epoller
|
|
|
+ */
|
|
|
+ TC_Epoller* _epoller = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * net线程的id
|
|
|
+ */
|
|
|
+ size_t _threadId;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 线程索引
|
|
|
+ */
|
|
|
+ int _threadIndex;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 服务
|
|
|
+ */
|
|
|
+ TC_EpollServer * _epollServer = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关联的adapters
|
|
|
+ */
|
|
|
+ vector<BindAdapter*> _adapters;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 管理的连接链表
|
|
|
+ */
|
|
|
+ shared_ptr<ConnectionList> _list;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送队列
|
|
|
+ */
|
|
|
+ send_queue _sbuffer;
|
|
|
+
|
|
|
+ // /**
|
|
|
+ // * 空连接超时时间,单位是毫秒,默认值2s,
|
|
|
+ // * 该时间必须小于等于adapter自身的超时时间
|
|
|
+ // */
|
|
|
+ // int _iEmptyCheckTimeout;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * udp连接时接收包缓存大小,针对所有udp接收缓存有效
|
|
|
+ */
|
|
|
+ size_t _nUdpRecvBufferSize;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化对象
|
|
|
+ */
|
|
|
+ std::function<void()> _initialize;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理对象
|
|
|
+ */
|
|
|
+ std::function<void()> _handle;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 具体处理基类
|
|
|
+ */
|
|
|
+ class Handle// : public TC_HandleBase
|
|
|
+ {
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 构造, 默认没有请求, 等待10s
|
|
|
+ */
|
|
|
+ Handle();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 析构函数
|
|
|
+ */
|
|
|
+ virtual ~Handle();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取服务
|
|
|
+ * @return TC_EpollServer*
|
|
|
+ */
|
|
|
+ inline TC_EpollServer *getEpollServer() const { return _epollServer; };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取adapter
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline BindAdapter *getBindAdapter() const { return _bindAdapter; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取Handle的索引(0~handle个数-1)
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline uint32_t getHandleIndex() const { return _handleIndex; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置网络线程
|
|
|
+ */
|
|
|
+ inline void setNetThread(NetThread *netThread) { _netThread = netThread; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取网络线程
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline NetThread *getNetThread() { return _netThread; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 结束
|
|
|
+ */
|
|
|
+ void terminate();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置数据队列
|
|
|
+ * @param data
|
|
|
+ */
|
|
|
+ inline void setDataBuffer(const shared_ptr<DataBuffer> &data) { _dataBuffer = data; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程处理一次
|
|
|
+ */
|
|
|
+ void handleOnceCoroutine();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 线程处理一次
|
|
|
+ */
|
|
|
+ void handleOnceThread();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程循环处理方法
|
|
|
+ */
|
|
|
+ void handleLoopCoroutine();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 线程循环处理方法
|
|
|
+ */
|
|
|
+ void handleLoopThread();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * handle是否启动准备好(协程进入调度状态)
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ bool isReady() const;
|
|
|
+ public:
|
|
|
+ /**
|
|
|
+ * 发送数据
|
|
|
+ * @param stRecvData
|
|
|
+ * @param sSendBuffer
|
|
|
+ */
|
|
|
+ inline void sendResponse(const shared_ptr<SendContext> & data) { _epollServer->send(data); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭链接(tcp连接才有效)
|
|
|
+ * @param stRecvData
|
|
|
+ */
|
|
|
+ inline void close(const shared_ptr<RecvContext> & data) { _epollServer->close(data);}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 对象初始化
|
|
|
+ */
|
|
|
+ virtual void initialize() { };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 唤醒handle对应的处理线程
|
|
|
+ */
|
|
|
+ virtual void notifyFilter();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 心跳(每处理完一个请求或者等待请求超时都会调用一次)
|
|
|
+ */
|
|
|
+ virtual void heartbeat() { }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程处理
|
|
|
+ */
|
|
|
+ void handleCoroutine();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置等待队列的时间
|
|
|
+ * @param iWaitTime
|
|
|
+ */
|
|
|
+ void setWaitTime(uint32_t iWaitTime);
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * 处理函数
|
|
|
+ * @param stRecvData: 接收到的数据
|
|
|
+ */
|
|
|
+ virtual void handle(const shared_ptr<RecvContext> & data) = 0;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理超时数据, 即数据在队列中的时间已经超过
|
|
|
+ * 默认直接关闭连接
|
|
|
+ * @param stRecvData: 接收到的数据
|
|
|
+ */
|
|
|
+ virtual void handleTimeout(const shared_ptr<RecvContext> & data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理连接关闭通知,包括
|
|
|
+ * 1.close by peer
|
|
|
+ * 2.recv/send fail
|
|
|
+ * 3.close by timeout or overload
|
|
|
+ * @param stRecvData:
|
|
|
+ */
|
|
|
+ virtual void handleClose(const shared_ptr<RecvContext> & data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理overload数据 即数据队列中长度已经超过允许值
|
|
|
+ * 默认直接关闭连接
|
|
|
+ * @param stRecvData: 接收到的数据
|
|
|
+ */
|
|
|
+ virtual void handleOverload(const shared_ptr<RecvContext> & data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 处理异步回调队列
|
|
|
+ */
|
|
|
+ virtual void handleAsyncResponse() { }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * handleFilter拆分的第二部分,处理用户自有数据
|
|
|
+ * 非游戏逻辑可忽略bExpectIdle参数
|
|
|
+ */
|
|
|
+ virtual void handleCustomMessage(bool bExpectIdle = false) { }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否所有的Adpater队列都为空
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ virtual bool allAdapterIsEmpty();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 是否所有的servant都没有resp消息待处理
|
|
|
+ * @return bool
|
|
|
+ */
|
|
|
+ virtual bool allFilterIsEmpty();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置服务
|
|
|
+ * @param pEpollServer
|
|
|
+ */
|
|
|
+ inline void setEpollServer(TC_EpollServer *pEpollServer) { _epollServer = pEpollServer; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置Adapter
|
|
|
+ * @param pEpollServer
|
|
|
+ */
|
|
|
+ inline void setBindAdapter(BindAdapter *bindAdapter) { _bindAdapter = bindAdapter; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置index
|
|
|
+ * @param index
|
|
|
+ */
|
|
|
+ inline void setHandleIndex(uint32_t index) { _handleIndex = index; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 友元类
|
|
|
+ */
|
|
|
+ friend class BindAdapter;
|
|
|
+ friend class TC_EpollServer;
|
|
|
+ protected:
|
|
|
+ /**
|
|
|
+ * 服务
|
|
|
+ */
|
|
|
+ TC_EpollServer * _epollServer;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * handle对应的网路线程(网络线程和handle线程合并的情况下有效)
|
|
|
+ */
|
|
|
+ NetThread * _netThread = NULL;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 所属handle组
|
|
|
+ */
|
|
|
+ BindAdapter * _bindAdapter;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数据队列
|
|
|
+ */
|
|
|
+ shared_ptr<DataBuffer> _dataBuffer;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Handle的索引
|
|
|
+ */
|
|
|
+ uint32_t _handleIndex;
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 结束
|
|
|
+// */
|
|
|
+// bool _terminate = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程模式下有效
|
|
|
+ */
|
|
|
+ shared_ptr<TC_CoroutineScheduler> _scheduler;
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 几种服务模式
|
|
|
+ */
|
|
|
+ enum SERVER_OPEN_COROUTINE
|
|
|
+ {
|
|
|
+ //独立网路线程 + 独立handle线程: 网络线程负责收发包, 通过队列唤醒handle线程中处理
|
|
|
+ NET_THREAD_QUEUE_HANDLES_THREAD = 0,
|
|
|
+ //独立网路线程组 + 独立handle线程: 网络线程负责收发包, 通过队列唤醒handle线程中处理, handle线程中启动协程处理
|
|
|
+ NET_THREAD_QUEUE_HANDLES_CO = 1,
|
|
|
+ //合并网路线程 + handle线程(线程个数以处理线程配置为准, 网络线程配置无效): 连接分配到不同线程中处理(如果是UDP, 则网络线程竞争接收包), 这种模式下延时最小, 相当于每个包的收发以及业务处理都在一个线程中
|
|
|
+ NET_THREAD_MERGE_HANDLES_THREAD = 2,
|
|
|
+ //合并网路线程 + handle线程(线程个数以处理线程配置为准, 网络线程配置无效): 连接分配到不同线程中处理(如果是UDP, 则网络线程竞争接收包), 每个包会启动协程来处理
|
|
|
+ NET_THREAD_MERGE_HANDLES_CO = 3
|
|
|
+ };
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 构造函数
|
|
|
+ */
|
|
|
+ TC_EpollServer(unsigned int iNetThreadNum=1);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 析构函数
|
|
|
+ */
|
|
|
+ virtual ~TC_EpollServer();
|
|
|
+
|
|
|
+ /**
|
|
|
+ *设置空连接超时时间(timeout>0: 启动, timeout<=0: 不做连接超时控制)
|
|
|
+ */
|
|
|
+ void setEmptyConnTimeout(int timeout);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置本地日志
|
|
|
+ * @param plocalLogger
|
|
|
+ */
|
|
|
+ inline void setLocalLogger(RollWrapperInterface *pLocalLogger) { _pLocalLogger = pLocalLogger; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取server type
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline SERVER_OPEN_COROUTINE getOpenCoroutine() const { return _openCoroutine; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * set server type
|
|
|
+ * @param serverType
|
|
|
+ */
|
|
|
+ void setOpenCoroutine(SERVER_OPEN_COROUTINE serverPatten);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置单线程中协程使用的堆栈大小
|
|
|
+ * 注意单线程协程消耗的内存: iPoolSize * iStackSize
|
|
|
+ * @param iPoolSize: 协程池大小(最多多少个协程) (默认服务内置的是1w个)
|
|
|
+ * @param iStackSize: 每个协程的堆栈大小(比如64k: 64*1024)
|
|
|
+ */
|
|
|
+ void setCoroutineStack(uint32_t iPoolSize, size_t iStackSize);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取协程池大小
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ uint32_t getCoroutinePoolSize() const { return _iCoroutinePoolSize; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取协程堆栈对消
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ size_t getCoroutineStackSize() const { return _iCoroutineStackSize; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置线程数量(非merge的情况下有效)
|
|
|
+ * @param threadNum
|
|
|
+ */
|
|
|
+ void setThreadNum(int threadNum)
|
|
|
+ {
|
|
|
+ _threadNum = threadNum;
|
|
|
+ if (_threadNum <= 0) _threadNum = 1;
|
|
|
+ if (_threadNum > 15) _threadNum = 15;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 创建BindAdpater
|
|
|
+ * @param name: adapter 名称
|
|
|
+ * @param ep: 服务绑定地址
|
|
|
+ * @param handleNum: handle处理线程个数
|
|
|
+ * @param args: Handle构造函数需要的参数
|
|
|
+ */
|
|
|
+ template<typename T, typename ...Args>
|
|
|
+ BindAdapterPtr createBindAdapter(const string &name, const string &ep, size_t handleNum, Args&&... args)
|
|
|
+ {
|
|
|
+ TC_EpollServer::BindAdapterPtr adapter = getBindAdapter(name);
|
|
|
+ if(adapter)
|
|
|
+ {
|
|
|
+ throw TC_EpollServer_Exception("[TC_EpollServer::createBindAdapter] adapter '" + name +"' has exists.");
|
|
|
+ }
|
|
|
+
|
|
|
+ adapter = std::make_shared<TC_EpollServer::BindAdapter>(this);
|
|
|
+
|
|
|
+ adapter->setName(name);
|
|
|
+ adapter->setEndpoint(ep);
|
|
|
+ adapter->setMaxConns(10240);
|
|
|
+ adapter->setHandle<T>(handleNum, args...);
|
|
|
+
|
|
|
+ return adapter;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 绑定监听socket
|
|
|
+ * @param ls
|
|
|
+ */
|
|
|
+ int bind(BindAdapterPtr &lsPtr);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 初始化handle对象
|
|
|
+ */
|
|
|
+ void initHandle();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 启动业务处理线程
|
|
|
+ */
|
|
|
+ void startHandle();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 生成epoll
|
|
|
+ * Generate epoll
|
|
|
+ */
|
|
|
+ void createEpoll();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 等待处理线程/协程都启动成功
|
|
|
+ */
|
|
|
+ void waitForReady();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 运行
|
|
|
+ */
|
|
|
+ void waitForShutdown();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 停止服务
|
|
|
+ */
|
|
|
+ void terminate();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 终止
|
|
|
+ */
|
|
|
+ inline bool isTerminate() const { return _epoller == NULL || _epoller->isTerminate(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取epoller地址
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ inline TC_Epoller *getEpoller() { return _epoller; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 根据名称获取BindAdapter
|
|
|
+ * @param sName
|
|
|
+ * @return BindAdapterPtr
|
|
|
+ */
|
|
|
+ BindAdapterPtr getBindAdapter(const string &sName);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所有adatapters
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ vector<BindAdapterPtr> getBindAdapters();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 关闭连接
|
|
|
+ * @param uid
|
|
|
+ */
|
|
|
+ void close(const shared_ptr<RecvContext> &data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送数据
|
|
|
+ * @param uid
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ void send(const shared_ptr<SendContext> &data);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取某一监听端口的连接数
|
|
|
+ * @param lfd
|
|
|
+ *
|
|
|
+ * @return vector<ConnStatus>
|
|
|
+ */
|
|
|
+ vector<ConnStatus> getConnStatus(int lfd);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取监听socket信息
|
|
|
+ *
|
|
|
+ * @return map<int,ListenSocket>
|
|
|
+ */
|
|
|
+ unordered_map<int, BindAdapterPtr> getListenSocketInfo();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所有连接的数目
|
|
|
+ *
|
|
|
+ * @return size_t
|
|
|
+ */
|
|
|
+ size_t getConnectionCount();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void debug(const string &s) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * INFO日志
|
|
|
+ * INFO LOG
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void info(const string &s) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * taf日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void tars(const string &s) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 记录错误日志
|
|
|
+ * @param s
|
|
|
+ */
|
|
|
+ virtual void error(const string &s) const;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取网络线程的数目
|
|
|
+ */
|
|
|
+ inline unsigned int getNetThreadNum() const { return _netThreads.size(); }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取网络线程的指针集合
|
|
|
+ */
|
|
|
+ inline const vector<NetThread *> &getNetThread() const { return _netThreads; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 停止线程
|
|
|
+ */
|
|
|
+ void stopThread();
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 获取所有业务线程的数目
|
|
|
+ */
|
|
|
+ size_t getLogicThreadNum();
|
|
|
+
|
|
|
+ //回调给应用服务
|
|
|
+ typedef std::function<void(TC_EpollServer *)> application_callback_functor;
|
|
|
+
|
|
|
+ //网络线程发送心跳的函数
|
|
|
+ //Function for network threads to send heartbeats
|
|
|
+ typedef std::function<void(const string &)> heartbeat_callback_functor;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置waitForShutdown线程回调的心跳
|
|
|
+ * @param hf [description]
|
|
|
+ */
|
|
|
+ void setCallbackFunctor(const application_callback_functor &hf) { _hf = hf; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置退出前的回调
|
|
|
+ * @param hf [description]
|
|
|
+ */
|
|
|
+ void setDestroyAppFunctor(const application_callback_functor &qf) { _qf = qf; }
|
|
|
+
|
|
|
+ // 接收新的客户端链接时的回调
|
|
|
+ typedef std::function<void (TC_EpollServer::Connection*)> accept_callback_functor;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 设置接收链接的回调
|
|
|
+ */
|
|
|
+ void setOnAccept(const accept_callback_functor& f) { _acceptFunc = f; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 设置netthread网络线程发送心跳的函数
|
|
|
+ * Function for setting netthreaded network threads to send heartbeats
|
|
|
+ * @param hf [description]
|
|
|
+ */
|
|
|
+ void setHeartBeatFunctor(const heartbeat_callback_functor &heartFunc) { _heartFunc = heartFunc; }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 心跳函数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ heartbeat_callback_functor &getHeartBeatFunctor() { return _heartFunc; }
|
|
|
+
|
|
|
+ friend class BindAdapter;
|
|
|
+
|
|
|
+protected:
|
|
|
+
|
|
|
+ /**
|
|
|
+ * accept callback
|
|
|
+ * @param data
|
|
|
+ */
|
|
|
+ bool acceptCallback(const shared_ptr<TC_Epoller::EpollInfo> &info, weak_ptr<BindAdapter> adapter);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * listen callback
|
|
|
+ * @param data
|
|
|
+ */
|
|
|
+ void listenCallback(weak_ptr<BindAdapter> adapterPtr);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收句柄
|
|
|
+ * @param fd
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ bool accept(int fd, int domain = AF_INET);
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 通知线程ready了
|
|
|
+ */
|
|
|
+ void notifyThreadReady();
|
|
|
+
|
|
|
+ static void applicationCallback(TC_EpollServer *epollServer);
|
|
|
+
|
|
|
+private:
|
|
|
+ /**
|
|
|
+ * server 模式
|
|
|
+ */
|
|
|
+ SERVER_OPEN_COROUTINE _openCoroutine = NET_THREAD_QUEUE_HANDLES_THREAD;
|
|
|
+
|
|
|
+// /**
|
|
|
+// * 是否已经结束
|
|
|
+// */
|
|
|
+// bool _terminate = false;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 网络线程
|
|
|
+ */
|
|
|
+ std::vector<NetThread *> _netThreads;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * epoll
|
|
|
+ */
|
|
|
+ TC_Epoller *_epoller = NULL;
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 线程数量
|
|
|
+ */
|
|
|
+ int _threadNum = 1;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 已经准备ready的线程数
|
|
|
+ */
|
|
|
+ std::atomic<int> _readyThreadNum{0};
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 锁
|
|
|
+ */
|
|
|
+ std::mutex _readyMutex;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 条件变量, 用来等待网络线程启动
|
|
|
+ */
|
|
|
+ std::condition_variable _readyCond;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * handle处理的线程池(merge模式下无效)
|
|
|
+ */
|
|
|
+ TC_ThreadPool _handlePool;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 本地循环日志
|
|
|
+ */
|
|
|
+ RollWrapperInterface *_pLocalLogger;
|
|
|
+
|
|
|
+ /**
|
|
|
+ *
|
|
|
+ */
|
|
|
+ vector<BindAdapterPtr> _bindAdapters;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 监听socket
|
|
|
+ */
|
|
|
+ unordered_map<int, BindAdapterPtr> _listeners;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 协程池大小
|
|
|
+ */
|
|
|
+ uint32_t _iCoroutinePoolSize = 10000;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 堆栈大小
|
|
|
+ */
|
|
|
+ size_t _iCoroutineStackSize = 64*1024;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 应用回调
|
|
|
+ */
|
|
|
+ application_callback_functor _hf;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 退出前的回调
|
|
|
+ */
|
|
|
+ application_callback_functor _qf;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 发送心跳的函数
|
|
|
+ * Heartbeat Sending Function
|
|
|
+ */
|
|
|
+ heartbeat_callback_functor _heartFunc;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 接收链接的回调函数
|
|
|
+ */
|
|
|
+ accept_callback_functor _acceptFunc;
|
|
|
+};
|
|
|
+
|
|
|
+typedef TC_AutoPtr<TC_EpollServer> TC_EpollServerPtr;
|
|
|
+
|
|
|
+}
|
|
|
+
|