提交 7bf5fe20 编写于 作者: W wolf 提交者: youngwolf

Disable heartbeat by default.

Sync doc.
Version number keeps unchanged.
上级 6251fb2d
......@@ -29,7 +29,7 @@ udp解包器必须实现这个接口。
2. 类
scope_atomic_lock:
功能与std::scope_lock一致,只是它执行atomic的++和--操作,而不是调用mutex的lock和unlock
功能与std::scope_lock一致,只是它是lock-free的,用原子操作代替了mutex操作
dummy_packer:
仅仅提供发送消息的类型以便通过编译,无法真正的打包,所以只能通过direct_send_msg等发送消息。
......
......@@ -135,7 +135,7 @@ static_assert(ASCS_GRACEFUL_SHUTDOWN_MAX_DURATION > 0, "graceful shutdown durati
//how many async_accept delivery concurrently
#ifndef ASCS_ASYNC_ACCEPT_NUM
#define ASCS_ASYNC_ACCEPT_NUM 1
#define ASCS_ASYNC_ACCEPT_NUM 16
#endif
static_assert(ASCS_ASYNC_ACCEPT_NUM > 0, "async accept number must be bigger than zero.");
同时投递多少个async_accept。
......@@ -195,4 +195,22 @@ ascs默认提供了三种消息队列供你选择,一是concurrent queue,它
可以参看ascs::lock_free_queue,ascs::non_lock_queue及ascs::lock_queue,需要支持两个模板参数。
容器需要实现一些特定的接口(队列需要调用),可以参看moodycamel::ConcurrentQueue以及ascs::list,需要支持一个模板参数,至于确切的需要实现哪些接口,
因不同的队列而不同,最好的办法就是编译,让编译器告诉你缺少哪些接口,接口从名称上就可以看出其作用,非常清晰。
//#define ASCS_SCATTERED_RECV_BUFFER
是否支持scatter-gather缓存,即一次提供多个不连续的缓存用于接收消息,如果你使用了ring buffer,相信你知道我在说什么。
#ifndef ASCS_HEARTBEAT_INTERVAL
#define ASCS_HEARTBEAT_INTERVAL 5 //second(s)
#endif
发送心跳包间隔,在此间隔中,如果有消息被接收或者被成功发送,将不会发送心跳包,直到下一个间隔再发。
心跳包通过OOB通道实现。注意,从linux发送心跳包到windows,接收方会把心跳包当成普通的数据而造成解包失败,原因未知。
如果想关闭心跳包,定义这个宏为0即可,此时你仍然可以以自己的逻辑来发送接收心跳包,并判断连接的有效性,只需要你调用connector_base::check_heartbeat或者
server_socket_base::check_heartbeat即可,非常简单。
#ifndef ASCS_HEARTBEAT_MAX_ABSENCE
#define ASCS_HEARTBEAT_MAX_ABSENCE 3 //times of ASCS_HEARTBEAT_INTERVAL
#endif
static_assert(ASCS_HEARTBEAT_MAX_ABSENCE > 0, "heartbeat absence must be bigger than zero.");
在ASCS_HEARTBEAT_INTERVAL * ASCS_HEARTBEAT_MAX_ABSENCE秒之内,如果没有任何数据收发,也没有收到心跳包,连接被认为是意外中断。注意,即便你自己调用
connector_base::check_heartbeat或者server_socket_base::check_heartbeat,这个宏仍然需要,所以它必须大于0。
//configurations
......@@ -34,10 +34,10 @@ class non_copy_unpacker : public i_unpacker<basic_buffer>;
这两个消息不解释,注意没有返回replaceable_buffer的fixed_length_unpacker和prefix_suffix_unpacker,可参考
replaceable_unpacker自行实现。
class fixed_length_unpacker : public i_unpacker<std::string>;
class prefix_suffix_unpacker : public i_unpacker<std::string>;
class fixed_length_unpacker : public tcp::i_unpacker<basic_buffer>;
class prefix_suffix_unpacker : public tcp::i_unpacker<std::string>;
class stream_unpacker : public tcp::i_unpacker<std::string>
class stream_unpacker : public tcp::i_unpacker<std::string>;
无协议解包器,收到什么就是什么,类似于调试助手。
}} //namespace
......
......@@ -20,11 +20,16 @@ protected:
static const tid TIMER_END = TIMER_BEGIN + 10;
socket(asio::io_service& io_service_);
template<typename Arg>
socket(asio::io_service& io_service_, Arg& arg);
ssl使用。
void first_init();
构造时调用,仅仅是为了节省代码量而已,因为我们有两个构造函数都将调用它。
void reset();
被重用是调用。
void reset_state();
重置所有状态。
......@@ -32,7 +37,13 @@ ssl使用。
清空所有buffer。
public:
typedef obj_with_begin_time<InMsgType> in_msg;
typedef obj_with_begin_time<OutMsgType> out_msg;
typedef InQueue<in_msg, InContainer<in_msg>> in_container_type;
typedef OutQueue<out_msg, OutContainer<out_msg>> out_container_type;
uint_fast64_t id() const;
bool is_equal_to(uint_fast64_t id) const;
获取id。
Socket& next_layer();
......@@ -50,9 +61,6 @@ asio::ssl::stream<asio::ip::tcp::socket>对象及其从它们继承的对象。
是否已经开始,已经开始意思是已经调用过start()了,多次调用start()会有严重的包乱顺问题,好在我在某个版本
增加了防止多次调用start()的功能,之前靠用户保证,现在ascs库可以保证,即使用户多次调用也没问题。
boos started() const;
是否已经调用过下面的start函数,多次调用start是没有意义的,只有第一次调用有效。
void start();
开始,开始的动作由子类实现,本函数只是简单的判断start是否已经被调用过了,如果没有,则调用do_start函数(纯虚)。
......@@ -66,6 +74,8 @@ socket内部有消息发送缓存,当连接未建立的时候,用户仍然
暂停/恢复消息发送,这里指暂停/恢复真正的消息发送,所以就算暂停了消息发送,在发送缓存可用的情况下,send_msg和send_safe_msg
仍然可以成功调用。
注意,如果消息发送处于暂停状态,则safe_send_msg在发送缓存溢出的情况下,马上返回失败,而不是等待发送缓存直到可用为止。
bool is_sending_msg() const;
是否正在发送数据。
void suspend_dispatch_msg(bool suspend);
bool suspend_dispatch_msg() const;
......@@ -76,6 +86,24 @@ socket内部有消息发送缓存,当连接未建立的时候,用户仍然
消息派发,这样消息就不会乱序,否则由于你开启线程之后,马上退出了on_msg或者on_msg_handle,那么下一条消息(如果有的话)将马上被
派发,这样就出现了乱序问题(前一条消息还未处理完,后一条消息就被派发了)。
bool is_dispatching_msg() const;
是否正在派发数据。
void congestion_control(bool enable);
bool congestion_control() const;
拥塞控制。
如果你在处理消息的过程中,发现无法处理当前这条消息(比如处理消息产生的回应消息会造成发送缓存溢出,或者其它必要条件还未准备好,
比如你要读取数据库,但数据库连接还未建立起来),那么你怎么办呢?第一是等,但一但阻塞在on_msg或者on_msg_handle,就阻塞了一个
service线程,service线程是非常有限的资源,除非你开了很多很多的service线程(这会严重影响效率,增加线程切换开销)。第二你可以开启拥塞控制,
然后在on_msg或者on_msg_handle里面返回false,代表无法处理当前这条消息。
具体来说,如果你在on_msg里面开启拥塞控制,那么马上停止通过on_msg派发剩下的消息,当前这条消息(你返回false的这条)进入接收缓存,并通过
on_msg_handle来派发,在on_msg_handle里面,如果你发现仍然处理不了,则继续返回false,直到你能够处理它,并在处理它之后(on_msg_handle里面)
关闭拥塞控制并返回true,那么剩下的消息将再次通过on_msg派发。
如果你在on_msg_handle里面处理消息,那返回false就是拥塞控制,不再需要调用congestion_control函数(调用也无效果)。
const struct statistic& get_statistic() const;
综合统计信息。
std::shared_ptr<i_packer<typename Packer::msg_type>> inner_packer();
std::shared_ptr<const i_packer<typename Packer::msg_type>> inner_packer() const;
......@@ -97,10 +125,6 @@ socket内部有消息发送缓存,当连接未建立的时候,用户仍然
size_t get_pending_recv_msg_num();
获取缓存里面的消息数量,其中post和send缓存里面的消息是打包过的;recv缓存里面的消息是解包过后的,下同。
void peek_first_pending_send_msg(InMsgType& msg);
void peek_first_pending_recv_msg(OutMsgType& msg);
偷看一下缓存中第一个包,如果得到一个空包(msg.empty()等于true),则说明缓存里面没有消息。
void pop_first_pending_send_msg(InMsgType& msg);
void pop_first_pending_recv_msg(OutMsgType& msg);
弹出缓存中第一个包,如果得到一个空包(msg.empty()等于true),则说明缓存里面没有消息。
......@@ -116,8 +140,13 @@ protected:
virtual bool do_send_msg() = 0;
真正的消息发送(调用asio函数),具体怎么发请看tcp::socket和udp::socket的实现。
virtual void do_recv_msg() = 0;
真正的消息接收(调用asio函数),具体怎么发请看tcp::socket和udp::socket的实现。
virtual bool is_closable();
当连接主动或者被被关闭时(shutdown),是否可以close它,只有close之后的对象才可以被释放或者被重用,默认返回true。
那么什么时候不是closable的呢,答案是设置了重连的connector_base,其它情况都是closable的,使用者通过重写这个函数,可以加
上自己的逻辑。
virtual bool is_send_allowed() const;
是否允许发送消息,对于socket来说,只要未暂停消息发送,就是允许消息发送,子类重写这个函数实现自己的判断逻辑,然后加上
......@@ -156,9 +185,12 @@ socket的判断结果,最终确认是否可发送数据。请看tcp::socket、
如果定义了ASCS_DELAY_CLOSE宏且其值等于0,则socket将保证以上说的行为,如果没有定义,则简单地在ASCS_DELAY_CLOSE秒后,调用on_close(),
然后同样的道理,object_pool将完全接管这个socket,以便在适当的时候重用或者释放它。
void handle_msg();
子类收到消息之后,调用这个函数来派发消息,它要么直接调用on_msg,要么把消息放入消息接收缓存,然后调用dispatch_msg,如果消息处理完毕(调用on_msg)
或者都放入了消息接收缓存,则调用do_recv_msg以继续接收数据。
void dispatch_msg();
派发消息,它要么直接调用on_msg,要么把消息放入消息接收缓存,最后调用do_dispatch_msg,如果消息处理完毕(调用on_msg)
或者都放入了消息接收缓存,则调用do_start以继续接收数据。
派发消息(调用do_dispatch_msg)。
void do_dispatch_msg(bool need_lock);
调用io_service::post发出一个异步调用,调度到时回调msg_handler。
......@@ -168,11 +200,22 @@ private:
void id(uint_fast64_t id);
设置id,注意使用者不可设置id,只有socket的创建者(object_pool或者其继承者)才可设置id,除非这个socket没有被任何对象池管理。
bool timer_handler(timer::tid id);
bool timer_handler(tid id);
处理所有定时器
bool do_direct_send_msg(InMsgType&& msg);
将消息插入容器,内部使用。
private:
template<typename Object> friend class object_pool;
void id(uint_fast64_t id) {_id = id;}
设置id,只有object_pool可以调用。
bool timer_handler(tid id);
定时器回调函数。
void msg_handler();
异步派发接收缓存里面的消息时,asio调用本函数,在这个函数里面将调用on_msg_handle,然后调用do_dispatch_msg继承派发消息。
异步派发接收缓存里面的消息时,asio调用本函数,在这个函数里面将调用on_msg_handle,然后调用do_dispatch_msg或者dispatch_msg继续派发消息。
protected:
uint_fast64_t _id;
......@@ -182,24 +225,29 @@ protected:
out_msg last_dispatch_msg;
由于是异步发送和派发消息,这两个成员变量保证其在异步处理过程中的有效性。
std::shared_ptr<i_packer<MsgDataType>> packer_;
std::shared_ptr<i_packer<typename Packer::msg_type>> packer_;
打包器。
in_container_type send_msg_buffer;
out_container_type recv_msg_buffer;
list<out_msg> temp_msg_buffer;
std::list<out_msg> temp_msg_buffer;
收发缓存,访问temp_msg_buffer无需互斥,它只能在内部访问,作用是当收到消息之后,当消息无法存入接收缓存
(消息派发被暂停,或者正在拥塞控制),那么消息将被存放于temp_msg_buffer,并且不再继续接收消息,直到temp_msg_buffer
里面的消息全部被处理掉,或者移到了recv_msg_buffer,socket会周期性的做以上尝试。
bool sending, paused_sending;
std::shared_mutex send_mutex;
bool dispatching, paused_dispatching, congestion_controlling;
std::shared_mutex dispatch_mutex;
volatile bool sending;
bool paused_sending;
std::atomic_flag send_atomic;
volatile bool dispatching;
bool paused_dispatching;
std::atomic_flag dispatch_atomic;
volatile bool congestion_controlling;
内部使用的一些状态,看名字应该能猜到其意思。
bool started_; //has started or not
std::shared_mutex start_mutex;
volatile bool started_; //has started or not
std::atomic_flag start_atomic;
是否已经开始,开始的概念由子类具体实现,socket只是记录是否已经调用过start函数而已。
struct statistic stat;
......
......@@ -68,6 +68,10 @@ virtual int prepare_reconnect(const asio::error_code& ec);
bool prepare_next_reconnect(const asio::error_code& ec);
如果允许(io_service仍然在运行且prepare_reconnect返回大于等于0),启动定时器以延时一小段时间之后重新连接服务器。
bool check_heartbeat(int interval);
发送和读取心跳包,将做断线检测。
如果定义了ASCS_HEARTBEAT_INTERVAL,将自动调用这个函数,否则你也可以以自己的逻辑来调用它。
private:
bool async_shutdown_handler(timer::tid id, ssize_t loop_num);
异步优雅关闭(shutdown)超时定时器。
......
......@@ -44,9 +44,17 @@ protected:
virtual void on_recv_error(const error_code& ec);
连接断开,默认的行为是调用i_server::del_client,可以重写以自定义行为。
bool check_heartbeat(int interval);
发送和读取心跳包,将做断线检测。
如果定义了ASCS_HEARTBEAT_INTERVAL,将自动调用这个函数,否则你也可以以自己的逻辑来调用它。
private:
bool async_shutdown_handler(timer::tid id, size_t loop_num);
异步优雅关闭(shutdown)超时定时器。
protected:
Server& server;
用于操控server_base,server_base在创建(其实是object_pool,server_base是其子类)server_socket_base的时候,会把自己的引用通过构造函数传入。
用于操控server_base,server_base(其实是object_pool,server_base是其子类)在创建server_socket_base的时候,会把自己的引用通过构造函数传入。
};
}} //namespace
......
......@@ -17,11 +17,13 @@ protected:
enum shutdown_states {NONE, FORCE, GRACEFUL};
socket_base(asio::io_service& io_service_);
template<typename Arg>
socket_base(asio::io_service& io_service_, Arg& arg);
ssl使用。
void first_init();
构造时调用,仅仅是为了节省代码量而已,因为我们有两个构造函数都将调用它。
public:
virtual bool obsoleted();
在调用父类同名函数的基础上,增加了对是否正在关闭连接的判断,如果是,则返回假。
......@@ -32,8 +34,8 @@ public:
void reset_state();
重载父类同名函数,重置自己的状态之后,调用父类同名函数。
bool is_closing() const;
是否正在优雅关闭套接字,此时不再发送消息(如果发送会出错,因为已经关闭了自己的数据发送),但继续接收消息。
bool is_shutting_down() const {return shutdown_states::NONE != shutdown_state;}
是否正在优雅关闭套接字,此时不再发送消息(如果发送会出错,因为已经关闭了自己的数据发送),但继续接收消息。
std::shared_ptr<i_unpacker<out_msg_type>> inner_unpacker();
std::shared_ptr<const i_unpacker<out_msg_type>> inner_unpacker() const;
......@@ -65,19 +67,6 @@ safe系列函数,在on_msg和om_msg_handle里面调用时需要特别谨慎,
bool safe_send_native_msg(const char* const pstr[], const size_t len[], size_t num, bool can_overflow = false);
同上,只是以native为true调用i_packer::pack_msg接口。
bool post_msg(const char* pstr, size_t len, bool can_overflow = false);
bool post_msg(const std::string& str, bool can_overflow = false);
bool post_msg(const char* const pstr[], const size_t len[], size_t num, bool can_overflow = false);
同send_msg,只是它永远能马上成功。
注意:如果消息发送缓存溢出了(当然can_overflow得为false,否则不检测缓存是否溢出),则暂停消息派发(进而也会停止消息接收,
因为不派发只接收消息,迟早会让消息接收缓存满而暂停消息接收,如果不使用消息接收缓存,则马上暂停消息接收)。
post_msg和send_msg的区别请看st_socket里面的post_msg_buffer和send_msg_buffer。
bool post_native_msg(const char* pstr, size_t len, bool can_overflow = false);
bool post_native_msg(const std::string& str, bool can_overflow = false);
bool post_native_msg(const char* const pstr[], const size_t len[], size_t num, bool can_overflow = false);
同上,只是以native为true调用i_packer::pack_msg接口。
protected:
void force_shutdown();
void graceful_shutdown(bool sync);
......@@ -109,6 +98,10 @@ protected:
关闭套接字,停止所有定时器,直接派发所有剩余消息,最后启动一个定时器,如果定义了ASCS_ENHANCED_STABILITY宏,则这个将周期性的检测
当前套接字是否可以安全地被重用或释放,如果未定义,则简单的在ASCS_DELAY_CLOSE秒后认为当前大量接字可被安全地重用或释放。
int clean_heartbeat();
读取所有OOB数据,返回读到的OOB数据长度。
private:
void recv_handler(const error_code& ec, size_t bytes_transferred);
收到数据时后asio回调。
......@@ -116,12 +109,15 @@ protected:
成功发送消息(写入底层套接字)后由asio回调。
protected:
typename super::in_container_type last_send_msg;
list<typename super::in_msg> last_send_msg;
std::shared_ptr<i_unpacker<out_msg_type>> unpacker_;
shutdown_states shutdown_state;
std::atomic_size_t shutdown_atomic;
volatile shutdown_states shutdown_state;
std::atomic_flag shutdown_atomic;
让shutdown函数线程安全。
time_t last_interact_time;
上次交互时间,包括成功发送数据,成功接收数据和OOB数据,用于断线检测。
};
}} //namespace
......@@ -60,19 +60,6 @@ safe系列函数,在on_msg和om_msg_handle里面调用时需要特别谨慎,
bool safe_send_native_msg(const udp::endpoint& peer_addr, const char* const pstr[], const size_t len[], size_t num, bool can_overflow = false);
同上,只是以native为true调用i_packer::pack_msg接口。
bool post_msg(const udp::endpoint& peer_addr, const char* pstr, size_t len, bool can_overflow = false);
bool post_msg(const udp::endpoint& peer_addr, const std::string& str, bool can_overflow = false);
bool post_msg(const udp::endpoint& peer_addr, const char* const pstr[], const size_t len[], size_t num, bool can_overflow = false);
同send_msg,只是它永远能马上成功。
注意:如果消息发送缓存溢出了(当然can_overflow得为false,否则不检测缓存是否溢出),则暂停消息派发(进而也会停止消息接收,
因为不派发只接收消息,迟早会让消息接收缓存满而暂停消息接收,如果不使用消息接收缓存,则马上暂停消息接收)。
post_msg和send_msg的区别请看st_socket里面的post_msg_buffer和send_msg_buffer。
bool post_native_msg(const udp::endpoint& peer_addr, const char* pstr, size_t len, bool can_overflow = false);
bool post_native_msg(const udp::endpoint& peer_addr, const std::string& str, bool can_overflow = false);
bool post_native_msg(const udp::endpoint& peer_addr, const char* const pstr[], const size_t len[], size_t num, bool can_overflow = false);
同上,只是以native为true调用i_packer::pack_msg接口。
void show_info(const char* head, const char* tail);
打印日志,在head和tail中间加上本端ip和端口。
......
......@@ -8,7 +8,6 @@
//any value which is bigger than zero is okay.
#define ASCS_FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer
#define ASCS_CUSTOM_LOG
#define ASCS_HEARTBEAT_INTERVAL 0 //disable heartbeat just because echo_server disabled heartbeat.
#define ASCS_DEFAULT_UNPACKER non_copy_unpacker
//#define ASCS_DEFAULT_UNPACKER stream_unpacker
......
......@@ -13,7 +13,6 @@
#define ASCS_INPUT_QUEUE non_lock_queue //we will never operate sending buffer concurrently, so need no locks
#define ASCS_INPUT_CONTAINER list
#endif
#define ASCS_HEARTBEAT_INTERVAL 0 //disable heartbeat when doing performance test
//#define ASCS_MAX_MSG_NUM 16
//if there's a huge number of links, please reduce messge buffer via ASCS_MAX_MSG_NUM macro.
//please think about if we have 512 links, how much memory we can accupy at most with default ASCS_MAX_MSG_NUM?
......@@ -22,9 +21,9 @@
//use the following macro to control the type of packer and unpacker
#define PACKER_UNPACKER_TYPE 0
//0-default packer and unpacker, head(length) + body
//1-default replaceable_packer and replaceable_unpacker, head(length) + body
//2-fixed length unpacker
//3-prefix and suffix packer and unpacker
//1-replaceable packer and unpacker, head(length) + body
//2-fixed length packer and unpacker
//3-prefix and/or suffix packer and unpacker
#if 1 == PACKER_UNPACKER_TYPE
#define ASCS_DEFAULT_PACKER replaceable_packer<>
......
......@@ -9,7 +9,6 @@
#define ASCS_ENHANCED_STABILITY
//#define ASCS_FULL_STATISTIC //full statistic will slightly impact efficiency
//#define ASCS_USE_STEADY_TIMER
#define ASCS_HEARTBEAT_INTERVAL 0 //disable heartbeat when doing performance test
//#define ASCS_MAX_MSG_NUM 16
//if there's a huge number of links, please reduce messge buffer via ASCS_MAX_MSG_NUM macro.
//please think about if we have 512 links, how much memory we can accupy at most with default ASCS_MAX_MSG_NUM?
......@@ -18,9 +17,9 @@
//use the following macro to control the type of packer and unpacker
#define PACKER_UNPACKER_TYPE 0
//0-default packer and unpacker, head(length) + body
//1-default replaceable_packer and replaceable_unpacker, head(length) + body
//2-fixed length unpacker
//3-prefix and suffix packer and unpacker
//1-replaceable packer and unpacker, head(length) + body
//2-fixed length packer and unpacker
//3-prefix and/or suffix packer and unpacker
#if 1 == PACKER_UNPACKER_TYPE
#define ASCS_DEFAULT_PACKER replaceable_packer<>
......
......@@ -6,6 +6,7 @@
#define ASCS_DELAY_CLOSE 5 //define this to avoid hooks for async call (and slightly improve efficiency)
//#define ASCS_INPUT_QUEUE non_lock_queue
//we cannot use non_lock_queue, because we also send messages (talking messages) out of ascs::socket::on_msg_send().
#define ASCS_HEARTBEAT_INTERVAL 5
#define ASCS_DEFAULT_UNPACKER replaceable_unpacker<>
//configuration
......
......@@ -12,6 +12,7 @@
//sent to file_client, so sending buffer will always be empty, which means we will never operate sending buffer concurrently,
//so need no locks.
#define ASCS_INPUT_CONTAINER list
#define ASCS_HEARTBEAT_INTERVAL 5
#define ASCS_DEFAULT_PACKER replaceable_packer<>
//configuration
......
......@@ -10,6 +10,7 @@
//sent to file_client, so sending buffer will always be empty, which means we will never operate sending buffer concurrently,
//so need no locks.
#define ASCS_INPUT_CONTAINER list
#define ASCS_HEARTBEAT_INTERVAL 5
#define ASCS_DEFAULT_PACKER replaceable_packer<>
//configuration
......
......@@ -10,7 +10,6 @@
#define ASCS_MSG_BUFFER_SIZE 65536
#define ASCS_INPUT_QUEUE non_lock_queue //we will never operate sending buffer concurrently, so need no locks
#define ASCS_INPUT_CONTAINER list
#define ASCS_HEARTBEAT_INTERVAL 0 //disable heartbeat when doing performance test
#define ASCS_DEFAULT_UNPACKER stream_unpacker //non-protocol
//configuration
......
......@@ -15,7 +15,6 @@
//
//if pingpong_client send message in on_msg_send(), then using non_lock_queue as input queue in pingpong_server will lead
//undefined behavior, please note.
#define ASCS_HEARTBEAT_INTERVAL 0 //disable heartbeat when doing performance test
#define ASCS_DEFAULT_UNPACKER stream_unpacker //non-protocol
//configuration
......
......@@ -87,6 +87,8 @@
*
* known issues:
* 1. heartbeat mechanism cannot work properly between windows (at least win-10) and Ubuntu (at least Ubuntu-16.04).
* 2. UDP doesn't support heartbeat because UDP doesn't support OOB data.
* 3. SSL doesn't support heartbeat (maybe I missed an option, I'm not familiar with SSL).
*
*/
......@@ -301,18 +303,21 @@ template<typename T> using concurrent_queue = moodycamel::ConcurrentQueue<T>;
//it's very useful under certain situations (for example, you're using ring buffer in unpacker).
#ifndef ASCS_HEARTBEAT_INTERVAL
#define ASCS_HEARTBEAT_INTERVAL 5 //second(s)
#define ASCS_HEARTBEAT_INTERVAL 0 //second(s), disable heartbeat by default, just for compatibility
#endif
//at every ASCS_HEARTBEAT_INTERVAL second(s), send an OOB data (heartbeat) if no normal messages been sent,
//less than or equal to zero means disable heartbeat, then you can send and check heartbeat with you own logic by calling connector_base::check_heartbeat
// or server_socket_base::check_heartbeat, and you still need to define a valid ASCS_HEARTBEAT_MAX_ABSENCE macro, please note.
//at every ASCS_HEARTBEAT_INTERVAL second(s):
// 1. connector_base will send an OOB data (heartbeat) if no normal messages been sent not received within this interval,
// 2. server_socket_base will try to recieve all OOB data (heartbeat) which has been recieved by system.
// 3. both endpoints will check the link's connectedness, see ASCS_HEARTBEAT_MAX_ABSENCE macro for more details.
//less than or equal to zero means disable heartbeat, then you can send and check heartbeat with you own logic by calling
//connector_base::check_heartbeat or server_socket_base::check_heartbeat, and you still need a valid ASCS_HEARTBEAT_MAX_ABSENCE, please note.
#ifndef ASCS_HEARTBEAT_MAX_ABSENCE
#define ASCS_HEARTBEAT_MAX_ABSENCE 3 //times of ASCS_HEARTBEAT_INTERVAL
#endif
static_assert(ASCS_HEARTBEAT_MAX_ABSENCE > 0, "heartbeat absence must be bigger than zero.");
//if no any data (include heartbeats) been received within ASCS_HEARTBEAT_INTERVAL * ASCS_HEARTBEAT_MAX_ABSENCE second(s), shut down the link.
//if no any messages been sent or received, nor any heartbeats been received within
//ASCS_HEARTBEAT_INTERVAL * ASCS_HEARTBEAT_MAX_ABSENCE second(s), shut down the link.
//configurations
#endif /* _ASCS_CONFIG_H_ */
......@@ -121,7 +121,7 @@ public:
virtual size_t raw_data_len(typename super::msg_ctype& msg) const {return msg.size() - ASCS_HEAD_LEN;}
};
//protocol: fixed lenght
//protocol: fixed length
class fixed_length_packer : public packer
{
public:
......
......@@ -272,7 +272,7 @@ private:
int step; //-1-error format, 0-want the head, 1-want the body
};
//protocol: fixed lenght
//protocol: fixed length
//non-copy
class fixed_length_unpacker : public tcp::i_unpacker<basic_buffer>
{
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册