提交 e61855ae 编写于 作者: Y youngwolf 提交者: youngowlf

Move packers and unpackers out of 'include' directory (now in 'ext'...

Move packers and unpackers out of 'include' directory (now in 'ext' directory), they don't belong to st_asio_wrapper library.
上级 372c9e02
......@@ -5,8 +5,8 @@
#define ST_ASIO_SERVER_PORT 9527
#define ST_ASIO_FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer
#define ST_ASIO_CUSTOM_LOG
//#define ST_ASIO_DEFAULT_UNPACKER unbuffered_unpacker
#define ST_ASIO_DEFAULT_UNPACKER stream_unpacker
#define ST_ASIO_DEFAULT_UNPACKER buffer_free_unpacker
//#define ST_ASIO_DEFAULT_UNPACKER stream_unpacker
//the following three macros demonstrate how to support huge msg(exceed 65535 - 2).
//huge msg will consume huge memory, for example, if we want to support 1M msg size, because every st_tcp_socket has a
......@@ -39,7 +39,8 @@ public:
static void debug_out(const char* fmt, ...) {all_out_helper2("debug");}
};
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......
......@@ -26,8 +26,9 @@
#endif
//configuration
#include "../include/st_asio_wrapper_server.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......@@ -129,7 +130,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: asio_server [service thread number=1] [<port=%d> [ip=0.0.0.0]]\n", ST_ASIO_SERVER_PORT);
printf("usage: asio_server [<service thread number=1> [<port=%d> [ip=0.0.0.0]]]\n", ST_ASIO_SERVER_PORT);
puts("normal server's port will be 100 larger.");
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
......@@ -194,20 +195,20 @@ int main(int argc, const char* argv[])
{
//broadcast series functions call pack_msg for each client respectively, because clients may used different protocols(so different type of packers, of course)
// server_.broadcast_msg(str.data(), str.size() + 1);
//send \0 character too, because asio_client used inflexible_buffer as its msg type, it will not append \0 character automatically as std::string does,
//send \0 character too, because asio_client used most_primitive_buffer as its msg type, it will not append \0 character automatically as std::string does,
//so need \0 character when printing it.
//if all clients used the same protocol, we can pack msg one time, and send it repeatedly like this:
// packer p;
// auto msg = p.pack_msg(str.data(), str.size() + 1);
//send \0 character too, because asio_client used inflexible_buffer as its msg type, it will not append \0 character automatically as std::string does,
packer p;
auto msg = p.pack_msg(str.data(), str.size() + 1);
//send \0 character too, because asio_client used most_primitive_buffer as its msg type, it will not append \0 character automatically as std::string does,
//so need \0 character when printing it.
// if (!msg.empty())
// server_.do_something_to_all([&msg](st_server_base<normal_server_socket>::object_ctype& item) {item->direct_send_msg(msg);});
if (!msg.empty())
server_.do_something_to_all([&msg](st_server_base<normal_server_socket>::object_ctype& item) {item->direct_send_msg(msg);});
//if asio_client is using stream_unpacker
if (!str.empty())
server_.do_something_to_all([&str](st_server_base<normal_server_socket>::object_ctype& item) {item->direct_send_msg(str);});
// if (!str.empty())
// server_.do_something_to_all([&str](st_server_base<normal_server_socket>::object_ctype& item) {item->direct_send_msg(str);});
}
}
......
......@@ -5,8 +5,8 @@
#define ST_ASIO_SERVER_PORT 9528
#define ST_ASIO_FORCE_TO_USE_MSG_RECV_BUFFER //force to use the msg recv buffer
#define ST_ASIO_CUSTOM_LOG
//#define ST_ASIO_DEFAULT_UNPACKER unbuffered_unpacker
#define ST_ASIO_DEFAULT_UNPACKER stream_unpacker
#define ST_ASIO_DEFAULT_UNPACKER buffer_free_unpacker
//#define ST_ASIO_DEFAULT_UNPACKER stream_unpacker
//the following three macros demonstrate how to support huge msg(exceed 65535 - 2).
//huge msg will consume huge memory, for example, if we want to support 1M msg size, because every st_tcp_socket has a
......@@ -39,7 +39,8 @@ public:
static void debug_out(const char* fmt, ...) {all_out_helper2("debug");}
};
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......
......@@ -26,8 +26,9 @@
#endif
//configuration
#include "../include/st_asio_wrapper_server.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......@@ -133,7 +134,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: asio_server [service thread number=1] [<port=%d> [ip=0.0.0.0]]\n", ST_ASIO_SERVER_PORT);
printf("usage: asio_server [<service thread number=1> [<port=%d> [ip=0.0.0.0]]]\n", ST_ASIO_SERVER_PORT);
puts("normal server's port will be 100 larger.");
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
......@@ -198,20 +199,20 @@ int main(int argc, const char* argv[])
{
//broadcast series functions call pack_msg for each client respectively, because clients may used different protocols(so different type of packers, of course)
// server_.broadcast_msg(str.data(), str.size() + 1);
//send \0 character too, because asio_client used inflexible_buffer as its msg type, it will not append \0 character automatically as std::string does,
//send \0 character too, because asio_client used most_primitive_buffer as its msg type, it will not append \0 character automatically as std::string does,
//so need \0 character when printing it.
//if all clients used the same protocol, we can pack msg one time, and send it repeatedly like this:
// packer p;
// packer::msg_type msg;
//send \0 character too, because asio_client used inflexible_buffer as its msg type, it will not append \0 character automatically as std::string does,
packer p;
packer::msg_type msg;
//send \0 character too, because asio_client used most_primitive_buffer as its msg type, it will not append \0 character automatically as std::string does,
//so need \0 character when printing it.
// if (p.pack_msg(msg, str.data(), str.size() + 1))
// server_.do_something_to_all(boost::bind((bool (normal_server_socket::*)(packer::msg_ctype&, bool)) &normal_server_socket::direct_send_msg, _1, boost::cref(msg), false));
if (p.pack_msg(msg, str.data(), str.size() + 1))
server_.do_something_to_all(boost::bind((bool (normal_server_socket::*)(packer::msg_ctype&, bool)) &normal_server_socket::direct_send_msg, _1, boost::cref(msg), false));
//if asio_client is using stream_unpacker
if (!str.empty())
server_.do_something_to_all(boost::bind((bool (normal_server_socket::*)(packer::msg_ctype&, bool)) &normal_server_socket::direct_send_msg, _1, boost::cref(str), false));
// if (!str.empty())
// server_.do_something_to_all(boost::bind((bool (normal_server_socket::*)(packer::msg_ctype&, bool)) &normal_server_socket::direct_send_msg, _1, boost::cref(str), false));
}
}
......
......@@ -7,8 +7,9 @@
#include <boost/lambda/lambda.hpp>
#include "../file_server/packer_unpacker.h"
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#if BOOST_VERSION >= 105300
extern boost::atomic_ushort completed_client_num;
......
......@@ -11,6 +11,7 @@
#include "../include/st_asio_wrapper_server.h"
using namespace st_asio_wrapper;
#include "file_socket.h"
#define QUIT_COMMAND "quit"
......
......@@ -2,9 +2,9 @@
#ifndef FILE_SOCKET_H_
#define FILE_SOCKET_H_
#include "../include/st_asio_wrapper_server_socket.h"
using namespace st_asio_wrapper;
#include "packer_unpacker.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper::ext;
class file_socket : public base_socket, public st_server_socket
{
......
#ifndef PACKER_UNPACKER_H_
#define PACKER_UNPACKER_H_
#include "../include/st_asio_wrapper_packer.h"
#include "../include/st_asio_wrapper_unpacker.h"
#include "../include/st_asio_wrapper_base.h"
using namespace st_asio_wrapper;
#ifdef _MSC_VER
......
/*
* st_asio_wrapper_ext.h
*
* Created on: 2016-7-30
* Author: youngwolf
* email: mail2tao@163.com
* QQ: 676218192
* Community on QQ: 198941541
*
* extensional, replaceable and indispensable components.
*/
#ifndef ST_ASIO_WRAPPER_EXT_H_
#define ST_ASIO_WRAPPER_EXT_H_
#include "../st_asio_wrapper_base.h"
#include "../st_asio_wrapper_client.h"
#include "../st_asio_wrapper_tcp_client.h"
#include "../st_asio_wrapper_udp_client.h"
#include "../st_asio_wrapper_server.h"
#include "st_asio_wrapper_packer.h"
#include "st_asio_wrapper_unpacker.h"
#ifndef ST_ASIO_DEFAULT_PACKER
#define ST_ASIO_DEFAULT_PACKER packer
#endif
#ifndef ST_ASIO_DEFAULT_UNPACKER
#define ST_ASIO_DEFAULT_UNPACKER unpacker
#endif
#ifndef ST_ASIO_DEFAULT_UDP_UNPACKER
#define ST_ASIO_DEFAULT_UDP_UNPACKER udp_unpacker
#endif
namespace st_asio_wrapper { namespace ext {
typedef st_server_socket_base<ST_ASIO_DEFAULT_PACKER, ST_ASIO_DEFAULT_UNPACKER> st_server_socket;
typedef st_server_base<st_server_socket> st_server;
typedef st_connector_base<ST_ASIO_DEFAULT_PACKER, ST_ASIO_DEFAULT_UNPACKER> st_connector;
typedef st_sclient<st_connector> st_tcp_sclient;
typedef st_tcp_client_base<st_connector> st_tcp_client;
typedef st_udp_socket_base<ST_ASIO_DEFAULT_PACKER, ST_ASIO_DEFAULT_UDP_UNPACKER> st_udp_socket;
typedef st_sclient<st_udp_socket> st_udp_sclient;
typedef st_udp_client_base<st_udp_socket> st_udp_client;
}} //namespace
#endif /* ST_ASIO_WRAPPER_EXT_H_ */
......@@ -13,7 +13,7 @@
#ifndef ST_ASIO_WRAPPER_PACKER_H_
#define ST_ASIO_WRAPPER_PACKER_H_
#include "st_asio_wrapper_base.h"
#include "../st_asio_wrapper_base.h"
#ifdef ST_ASIO_HUGE_MSG
#define ST_ASIO_HEAD_TYPE boost::uint32_t
......@@ -24,8 +24,7 @@
#endif
#define ST_ASIO_HEAD_LEN (sizeof(ST_ASIO_HEAD_TYPE))
namespace st_asio_wrapper
{
namespace st_asio_wrapper { namespace ext {
class packer_helper
{
......@@ -54,27 +53,6 @@ public:
}
};
template<typename MsgType>
class i_packer
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
protected:
virtual ~i_packer() {}
public:
virtual void reset_state() {}
virtual bool pack_msg(msg_type& msg, const char* const pstr[], const size_t len[], size_t num, bool native = false) = 0;
virtual char* raw_data(msg_type& msg) const {return NULL;}
virtual const char* raw_data(msg_ctype& msg) const {return NULL;}
virtual size_t raw_data_len(msg_ctype& msg) const {return 0;}
bool pack_msg(msg_type& msg, const char* pstr, size_t len, bool native = false) {return pack_msg(msg, &pstr, &len, 1, native);}
bool pack_msg(msg_type& msg, const std::string& str, bool native = false) {return pack_msg(msg, str.data(), str.size(), native);}
};
class packer : public i_packer<std::string>
{
public:
......@@ -121,6 +99,15 @@ public:
class replaceable_packer : public i_packer<replaceable_buffer>
{
public:
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
public:
using i_packer<msg_type>::pack_msg;
virtual bool pack_msg(msg_type& msg, const char* const pstr[], const size_t len[], size_t num, bool native = false)
......@@ -184,6 +171,6 @@ private:
std::string _prefix, _suffix;
};
} //namespace
}} //namespace
#endif /* ST_ASIO_WRAPPER_PACKER_H_ */
......@@ -14,9 +14,8 @@
#define ST_ASIO_WRAPPER_UNPACKER_H_
#include <boost/array.hpp>
#include <boost/container/list.hpp>
#include "st_asio_wrapper_base.h"
#include "../st_asio_wrapper_base.h"
#ifdef ST_ASIO_HUGE_MSG
#define ST_ASIO_HEAD_TYPE boost::uint32_t
......@@ -27,56 +26,7 @@
#endif
#define ST_ASIO_HEAD_LEN (sizeof(ST_ASIO_HEAD_TYPE))
namespace st_asio_wrapper
{
template<typename MsgType>
class i_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<msg_type> container_type;
protected:
virtual ~i_unpacker() {}
public:
virtual void reset_state() = 0;
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can) = 0;
virtual size_t completion_condition(const boost::system::error_code& ec, size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
template<typename MsgType>
class udp_msg : public MsgType
{
public:
boost::asio::ip::udp::endpoint peer_addr;
udp_msg() {}
udp_msg(const boost::asio::ip::udp::endpoint& _peer_addr) : peer_addr(_peer_addr) {}
void swap(udp_msg& other) {std::swap(peer_addr, other.peer_addr); MsgType::swap(other);}
void set_addr(const boost::asio::ip::udp::endpoint& addr) {peer_addr = addr;}
};
template<typename MsgType>
class i_udp_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<udp_msg<msg_type> > container_type;
protected:
virtual ~i_udp_unpacker() {}
public:
virtual void reset_state() {}
virtual void parse_msg(msg_type& msg, size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
namespace st_asio_wrapper { namespace ext {
class unpacker : public i_unpacker<std::string>
{
......@@ -192,6 +142,15 @@ protected:
class replaceable_unpacker : public i_unpacker<replaceable_buffer>
{
public:
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
public:
virtual void reset_state() {unpacker_.reset_state();}
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can)
......@@ -219,6 +178,15 @@ protected:
class replaceable_udp_unpacker : public i_udp_unpacker<replaceable_buffer>
{
public:
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
public:
virtual void parse_msg(msg_type& msg, size_t bytes_transferred)
{
......@@ -233,15 +201,42 @@ protected:
boost::array<char, ST_ASIO_MSG_BUFFER_SIZE> raw_buff;
};
//this unpacker demonstrate how to forbid memory copy while parsing msgs.
class unbuffered_unpacker : public i_unpacker<inflexible_buffer>
class most_primitive_buffer
{
public:
unbuffered_unpacker() {reset_state();}
most_primitive_buffer() {do_detach();}
~most_primitive_buffer() {free();}
void assign(size_t _len) {free(); do_attach(new char[_len], _len);}
void free() {delete buff; do_detach();}
//the following five functions (char* data() is used by unpackers, not counted in) are needed by st_asio_wrapper,
//for other functions, depends on the implementation of your packer and unpacker.
bool empty() const {return 0 == len || NULL == buff;}
size_t size() const {return len;}
const char* data() const {return buff;}
char* data() {return buff;}
void swap(most_primitive_buffer& other) {std::swap(buff, other.buff); std::swap(len, other.len);}
void clear() {free();}
protected:
void do_attach(char* _buff, size_t _len) {buff = _buff; len = _len;}
void do_detach() {buff = NULL; len = 0;}
protected:
char* buff;
size_t len;
};
//this unpacker demonstrate how to forbid memory copying while parsing msgs (let asio write msg directly).
class buffer_free_unpacker : public i_unpacker<most_primitive_buffer>
{
public:
buffer_free_unpacker() {reset_state();}
size_t current_msg_length() const {return raw_buff.size();} //current msg's total length(not include the head), 0 means don't know
public:
virtual void reset_state() {raw_buff.detach(); step = 0;}
virtual void reset_state() {raw_buff.clear(); step = 0;}
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can)
{
if (0 == step) //the head been received
......@@ -279,7 +274,16 @@ public:
if (0 == step) //want the head
{
assert(raw_buff.empty());
return boost::asio::detail::default_max_transfer_size;
if (bytes_transferred < ST_ASIO_HEAD_LEN)
return boost::asio::detail::default_max_transfer_size;
assert(ST_ASIO_HEAD_LEN == bytes_transferred);
size_t cur_msg_len = ST_ASIO_HEAD_N2H(head) - ST_ASIO_HEAD_LEN;
if (cur_msg_len > ST_ASIO_MSG_BUFFER_SIZE - ST_ASIO_HEAD_LEN) //invalid msg, stop reading
step = -1;
else
raw_buff.assign(cur_msg_len);
}
else if (1 == step) //want the body
{
......@@ -503,6 +507,6 @@ protected:
boost::array<char, ST_ASIO_MSG_BUFFER_SIZE> raw_buff;
};
} //namespace
}} //namespace
#endif /* ST_ASIO_WRAPPER_UNPACKER_H_ */
......@@ -19,8 +19,8 @@
#ifndef ST_ASIO_WRAPPER_H_
#define ST_ASIO_WRAPPER_H_
#define ST_ASIO_WRAPPER_VER 10002 //[x]xyyzz -> [x]x.[y]y.[z]z
#define ST_ASIO_WRAPPER_VERSION "1.0.2"
#define ST_ASIO_WRAPPER_VER 10100 //[x]xyyzz -> [x]x.[y]y.[z]z
#define ST_ASIO_WRAPPER_VERSION "1.1.0"
#ifdef _MSC_VER
#if _MSC_VER >= 1600
......
......@@ -24,6 +24,7 @@
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/container/list.hpp>
#include <boost/typeof/typeof.hpp>
#include "st_asio_wrapper.h"
......@@ -37,7 +38,7 @@
#elif ST_ASIO_MSG_BUFFER_SIZE <= 0
#error message buffer size must be bigger than zero.
#endif
//msg send and recv buffer's maximum size (list::size()), corresponding buffers are expanded dynamicly, which means only allocate memory when needed.
//msg send and recv buffer's maximum size (list::size()), corresponding buffers are expanded dynamically, which means only allocate memory when needed.
#ifndef ST_ASIO_MAX_MSG_NUM
#define ST_ASIO_MAX_MSG_NUM 1024
#elif ST_ASIO_MAX_MSG_NUM <= 0
......@@ -66,14 +67,7 @@ namespace st_asio_wrapper
virtual const char* data() const = 0;
};
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
//if you want to replace packer or unpacker at runtime, please use this as the msg type
class replaceable_buffer
{
public:
......@@ -96,43 +90,78 @@ namespace st_asio_wrapper
boost::shared_ptr<i_buffer> buffer;
};
//this buffer is more efficient than std::string if the memory is already allocated, because the replication been saved.
//for example, you are sending memory-mapped files.
class inflexible_buffer
//packer concept
template<typename MsgType>
class i_packer
{
public:
inflexible_buffer() {do_detach();}
~inflexible_buffer() {detach();}
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
void assign(const char* _buff, size_t _len)
{
assert(_len > 0 && NULL != _buff);
char* _buff_ = new char[_len];
memcpy(_buff_, _buff, _len);
attach(_buff_, _len);
}
protected:
virtual ~i_packer() {}
void attach(char* _buff, size_t _len) {detach(); do_attach(_buff, _len);}
void detach() {delete buff; do_detach();}
public:
virtual void reset_state() {}
virtual bool pack_msg(msg_type& msg, const char* const pstr[], const size_t len[], size_t num, bool native = false) = 0;
virtual char* raw_data(msg_type& msg) const {return NULL;}
virtual const char* raw_data(msg_ctype& msg) const {return NULL;}
virtual size_t raw_data_len(msg_ctype& msg) const {return 0;}
bool pack_msg(msg_type& msg, const char* pstr, size_t len, bool native = false) {return pack_msg(msg, &pstr, &len, 1, native);}
bool pack_msg(msg_type& msg, const std::string& str, bool native = false) {return pack_msg(msg, str.data(), str.size(), native);}
};
//packer concept
//the following five functions (char* data() is used by inflexible_unpacker, not counted) are needed by st_asio_wrapper,
//for other functions, depends on the implementation of your packer and unpacker.
bool empty() const {return 0 == len || NULL == buff;}
size_t size() const {return len;}
const char* data() const {return buff;}
char* data() {return buff;}
void swap(inflexible_buffer& other) {std::swap(buff, other.buff); std::swap(len, other.len);}
void clear() {detach();}
//unpacker concept
template<typename MsgType>
class i_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<msg_type> container_type;
protected:
void do_attach(char* _buff, size_t _len) {buff = _buff; len = _len;}
void do_detach() {buff = NULL; len = 0;}
virtual ~i_unpacker() {}
public:
virtual void reset_state() = 0;
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can) = 0;
virtual size_t completion_condition(const boost::system::error_code& ec, size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
template<typename MsgType>
class udp_msg : public MsgType
{
public:
boost::asio::ip::udp::endpoint peer_addr;
udp_msg() {}
udp_msg(const boost::asio::ip::udp::endpoint& _peer_addr) : peer_addr(_peer_addr) {}
void swap(udp_msg& other) {std::swap(peer_addr, other.peer_addr); MsgType::swap(other);}
void set_addr(const boost::asio::ip::udp::endpoint& addr) {peer_addr = addr;}
};
template<typename MsgType>
class i_udp_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<udp_msg<msg_type> > container_type;
protected:
char* buff;
size_t len;
virtual ~i_udp_unpacker() {}
public:
virtual void reset_state() {}
virtual void parse_msg(msg_type& msg, size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
//unpacker concept
//free functions, used to do something to any container(except map and multimap) optionally with any mutex
template<typename _Can, typename _Mutex, typename _Predicate>
......
......@@ -32,27 +32,30 @@
namespace st_asio_wrapper
{
template <typename Packer = ST_ASIO_DEFAULT_PACKER, typename Unpacker = ST_ASIO_DEFAULT_UNPACKER, typename Socket = boost::asio::ip::tcp::socket>
template <typename Packer, typename Unpacker, typename Socket = boost::asio::ip::tcp::socket>
class st_connector_base : public st_tcp_socket_base<Socket, Packer, Unpacker>
{
protected:
typedef st_tcp_socket_base<Socket, Packer, Unpacker> super;
public:
static const unsigned char TIMER_BEGIN = st_tcp_socket_base<Socket, Packer, Unpacker>::TIMER_END;
static const unsigned char TIMER_BEGIN = super::TIMER_END;
static const unsigned char TIMER_CONNECT = TIMER_BEGIN;
static const unsigned char TIMER_ASYNC_CLOSE = TIMER_BEGIN + 1;
static const unsigned char TIMER_END = TIMER_BEGIN + 10;
st_connector_base(boost::asio::io_service& io_service_) : st_tcp_socket_base<Socket, Packer, Unpacker>(io_service_), connected(false), reconnecting(true)
st_connector_base(boost::asio::io_service& io_service_) : super(io_service_), connected(false), reconnecting(true)
{set_server_addr(ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);}
template<typename Arg>
st_connector_base(boost::asio::io_service& io_service_, Arg& arg) : st_tcp_socket_base<Socket, Packer, Unpacker>(io_service_, arg), connected(false), reconnecting(true)
st_connector_base(boost::asio::io_service& io_service_, Arg& arg) : super(io_service_, arg), connected(false), reconnecting(true)
{set_server_addr(ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);}
//reset all, be ensure that there's no any operations performed on this st_connector_base when invoke it
//notice, when reusing this st_connector_base, st_object_pool will invoke reset(), child must re-write this to initialize
//all member variables, and then do not forget to invoke st_connector_base::reset() to initialize father's member variables
virtual void reset() {connected = false; reconnecting = true; st_tcp_socket_base<Socket, Packer, Unpacker>::reset();}
virtual bool obsoleted() {return !reconnecting && st_tcp_socket_base<Socket, Packer, Unpacker>::obsoleted();}
virtual void reset() {connected = false; reconnecting = true; super::reset();}
virtual bool obsoleted() {return !reconnecting && super::obsoleted();}
bool set_server_addr(unsigned short port, const std::string& ip = ST_ASIO_SERVER_IP)
{
......@@ -79,7 +82,7 @@ public:
connected = false;
}
st_tcp_socket_base<Socket, Packer, Unpacker>::force_close();
super::force_close();
}
//sync must be false if you call graceful_close in on_msg
......@@ -94,7 +97,7 @@ public:
reconnecting = reconnect;
connected = false;
if (st_tcp_socket_base<Socket, Packer, Unpacker>::graceful_close(sync))
if (super::graceful_close(sync))
ST_THIS set_timer(TIMER_ASYNC_CLOSE, 10, boost::bind(&st_connector_base::async_close_handler, this, _1, ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION * 100));
}
......@@ -133,7 +136,7 @@ protected:
//after how much time(ms), st_connector will try to reconnect to the server, negative means give up.
virtual int prepare_reconnect(const boost::system::error_code& ec) {return ST_ASIO_RECONNECT_INTERVAL;}
virtual void on_connect() {unified_out::info_out("connecting success.");}
virtual bool is_send_allowed() const {return is_connected() && st_tcp_socket_base<Socket, Packer, Unpacker>::is_send_allowed();}
virtual bool is_send_allowed() const {return is_connected() && super::is_send_allowed();}
virtual void on_unpack_error() {unified_out::info_out("can not unpack msg."); force_close();}
virtual void on_recv_error(const boost::system::error_code& ec)
{
......@@ -219,7 +222,6 @@ protected:
bool connected;
bool reconnecting;
};
typedef st_connector_base<> st_connector;
} //namespace
......
......@@ -37,7 +37,7 @@
namespace st_asio_wrapper
{
template<typename Socket = st_server_socket, typename Pool = st_object_pool<Socket>, typename Server = i_server>
template<typename Socket, typename Pool = st_object_pool<Socket>, typename Server = i_server>
class st_server_base : public Server, public Pool
{
public:
......@@ -156,7 +156,6 @@ protected:
boost::asio::ip::tcp::endpoint server_addr;
boost::asio::ip::tcp::acceptor acceptor;
};
typedef st_server_base<> st_server;
} //namespace
......
......@@ -27,22 +27,25 @@ public:
virtual bool del_client(const boost::shared_ptr<st_timer>& client_ptr) = 0;
};
template<typename Packer = ST_ASIO_DEFAULT_PACKER, typename Unpacker = ST_ASIO_DEFAULT_UNPACKER, typename Server = i_server, typename Socket = boost::asio::ip::tcp::socket>
template<typename Packer, typename Unpacker, typename Server = i_server, typename Socket = boost::asio::ip::tcp::socket>
class st_server_socket_base : public st_tcp_socket_base<Socket, Packer, Unpacker>, public boost::enable_shared_from_this<st_server_socket_base<Packer, Unpacker, Server, Socket> >
{
protected:
typedef st_tcp_socket_base<Socket, Packer, Unpacker> super;
public:
static const unsigned char TIMER_BEGIN = st_tcp_socket_base<Socket, Packer, Unpacker>::TIMER_END;
static const unsigned char TIMER_BEGIN = super::TIMER_END;
static const unsigned char TIMER_ASYNC_CLOSE = TIMER_BEGIN;
static const unsigned char TIMER_END = TIMER_BEGIN + 10;
st_server_socket_base(Server& server_) : st_tcp_socket_base<Socket, Packer, Unpacker>(server_.get_service_pump()), server(server_) {}
st_server_socket_base(Server& server_) : super(server_.get_service_pump()), server(server_) {}
template<typename Arg>
st_server_socket_base(Server& server_, Arg& arg) : st_tcp_socket_base<Socket, Packer, Unpacker>(server_.get_service_pump(), arg), server(server_) {}
st_server_socket_base(Server& server_, Arg& arg) : super(server_.get_service_pump(), arg), server(server_) {}
//reset all, be ensure that there's no any operations performed on this socket when invoke it
//please note, when reuse this socket, st_object_pool will invoke reset(), child must re-write it to initialize all member variables,
//and then do not forget to invoke st_server_socket_base::reset() to initialize father's member variables
virtual void reset() {st_tcp_socket_base<Socket, Packer, Unpacker>::reset();}
virtual void reset() {super::reset();}
void disconnect() {force_close();}
void force_close()
......@@ -50,7 +53,7 @@ public:
if (1 != ST_THIS close_state)
show_info("server link:", "been closed.");
st_tcp_socket_base<Socket, Packer, Unpacker>::force_close();
super::force_close();
}
void graceful_close(bool sync = true)
......@@ -58,7 +61,7 @@ public:
if (!ST_THIS is_closing())
show_info("server link:", "been closing gracefully.");
if (st_tcp_socket_base<Socket, Packer, Unpacker>::graceful_close(sync))
if (super::graceful_close(sync))
ST_THIS set_timer(TIMER_ASYNC_CLOSE, 10, boost::bind(&st_server_socket_base::async_close_handler, this, _1, ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION * 100));
}
......@@ -131,7 +134,6 @@ private:
protected:
Server& server;
};
typedef st_server_socket_base<> st_server_socket;
} //namespace
......
......@@ -18,17 +18,13 @@
#include <boost/date_time.hpp>
#include <boost/container/list.hpp>
#include "st_asio_wrapper_packer.h"
#include "st_asio_wrapper_base.h"
#include "st_asio_wrapper_timer.h"
#ifndef ST_ASIO_DEFAULT_PACKER
#define ST_ASIO_DEFAULT_PACKER packer
#endif
namespace st_asio_wrapper
{
template<typename Socket, typename Packer, typename Unpacker, typename InMsgType = typename Packer::msg_type, typename OutMsgType = typename Unpacker::msg_type>
template<typename Socket, typename Packer, typename Unpacker, typename InMsgType, typename OutMsgType>
class st_socket: public st_timer
{
public:
......@@ -351,45 +347,32 @@ protected:
//call this in recv_handler (in subclasses) only
void dispatch_msg()
{
bool overflow = false;
#ifndef ST_ASIO_FORCE_TO_USE_MSG_RECV_BUFFER
out_container_type temp_2_msg_buffer;
BOOST_AUTO(begin_time, statistic::local_time());
for (BOOST_AUTO(iter, temp_msg_buffer.begin()); !suspend_dispatch_msg_ && !posting && iter != temp_msg_buffer.end();)
if (on_msg(*iter))
temp_msg_buffer.erase(iter++);
else
temp_2_msg_buffer.splice(temp_2_msg_buffer.end(), temp_msg_buffer, iter++);
BOOST_AUTO(time_duration, statistic::local_time() - begin_time);
stat.handle_time_1_sum += time_duration;
stat.recv_idle_sum += time_duration;
if (!temp_2_msg_buffer.empty())
if (!temp_msg_buffer.empty())
{
#ifndef ST_ASIO_FORCE_TO_USE_MSG_RECV_BUFFER
out_container_type temp_2_msg_buffer;
BOOST_AUTO(begin_time, statistic::local_time());
for (BOOST_AUTO(iter, temp_msg_buffer.begin()); !suspend_dispatch_msg_ && !posting && iter != temp_msg_buffer.end();)
if (on_msg(*iter))
temp_msg_buffer.erase(iter++);
else
temp_2_msg_buffer.splice(temp_2_msg_buffer.end(), temp_msg_buffer, iter++);
BOOST_AUTO(time_duration, statistic::local_time() - begin_time);
stat.handle_time_1_sum += time_duration;
stat.recv_idle_sum += time_duration;
if (!temp_2_msg_buffer.empty())
{
boost::unique_lock<boost::shared_mutex> lock(recv_msg_buffer_mutex);
if (splice_helper(recv_msg_buffer, temp_2_msg_buffer))
do_dispatch_msg(false);
}
temp_msg_buffer.splice(temp_msg_buffer.begin(), temp_2_msg_buffer);
#else
boost::unique_lock<boost::shared_mutex> lock(recv_msg_buffer_mutex);
if (splice_helper(recv_msg_buffer, temp_2_msg_buffer))
if (splice_helper(recv_msg_buffer, temp_msg_buffer))
do_dispatch_msg(false);
}
temp_msg_buffer.splice(temp_msg_buffer.begin(), temp_2_msg_buffer);
#else
if (!temp_msg_buffer.empty())
{
if (suspend_dispatch_msg_ || posting)
overflow = true;
else
for (BOOST_AUTO(iter, temp_msg_buffer.begin()); iter != temp_msg_buffer.end();)
if (on_msg(*iter))
temp_msg_buffer.erase(iter++);
else
++iter;
}
#endif
if (!overflow)
{
boost::unique_lock<boost::shared_mutex> lock(recv_msg_buffer_mutex);
recv_msg_buffer.splice(recv_msg_buffer.end(), temp_msg_buffer);
overflow = recv_msg_buffer.size() > ST_ASIO_MAX_MSG_NUM;
do_dispatch_msg(false);
}
if (!overflow)
......
......@@ -19,18 +19,18 @@
namespace st_asio_wrapper
{
typedef st_sclient<st_connector> st_tcp_sclient;
template<typename Socket = st_connector, typename Pool = st_object_pool<Socket> >
template<typename Socket, typename Pool = st_object_pool<Socket> >
class st_tcp_client_base : public st_client<Socket, Pool>
{
protected:
typedef st_client<Socket, Pool> super;
public:
using st_client<Socket, Pool>::TIMER_BEGIN;
using st_client<Socket, Pool>::TIMER_END;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_tcp_client_base(st_service_pump& service_pump_) : st_client<Socket, Pool>(service_pump_) {}
st_tcp_client_base(st_service_pump& service_pump_) : super(service_pump_) {}
template<typename Arg>
st_tcp_client_base(st_service_pump& service_pump_, Arg arg) : st_client<Socket, Pool>(service_pump_, arg) {}
st_tcp_client_base(st_service_pump& service_pump_, Arg arg) : super(service_pump_, arg) {}
//connected link size, may smaller than total object size(st_object_pool::size)
size_t valid_size()
......@@ -43,7 +43,7 @@ public:
return size;
}
using st_client<Socket, Pool>::add_client;
using super::add_client;
typename Pool::object_type add_client()
{
BOOST_AUTO(client_ptr, ST_THIS create_object());
......@@ -79,7 +79,6 @@ public:
protected:
virtual void uninit() {ST_THIS stop(); graceful_close();}
};
typedef st_tcp_client_base<> st_tcp_client;
} //namespace
......
......@@ -14,7 +14,6 @@
#define ST_ASIO_WRAPPER_TCP_SOCKET_H_
#include "st_asio_wrapper_socket.h"
#include "st_asio_wrapper_unpacker.h"
#ifndef ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION
#define ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION 5 //seconds, maximum waiting seconds while graceful closing
......@@ -28,11 +27,9 @@
namespace st_asio_wrapper
{
namespace st_tcp
{
template <typename Socket, typename Packer, typename Unpacker>
class st_tcp_socket_base : public st_socket<Socket, Packer, Unpacker>
class st_tcp_socket_base : public st_socket<Socket, Packer, Unpacker, typename Packer::msg_type, typename Unpacker::msg_type>
{
public:
typedef typename Packer::msg_type in_msg_type;
......@@ -41,22 +38,23 @@ public:
typedef typename Unpacker::msg_ctype out_msg_ctype;
protected:
using st_socket<Socket, Packer, Unpacker>::TIMER_BEGIN;
using st_socket<Socket, Packer, Unpacker>::TIMER_END;
typedef st_socket<Socket, Packer, Unpacker, typename Packer::msg_type, typename Unpacker::msg_type> super;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_tcp_socket_base(boost::asio::io_service& io_service_) : st_socket<Socket, Packer, Unpacker>(io_service_), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
st_tcp_socket_base(boost::asio::io_service& io_service_) : super(io_service_), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
template<typename Arg>
st_tcp_socket_base(boost::asio::io_service& io_service_, Arg& arg) : st_socket<Socket, Packer, Unpacker>(io_service_, arg), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
st_tcp_socket_base(boost::asio::io_service& io_service_, Arg& arg) : super(io_service_, arg), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
public:
virtual bool obsoleted() {return !is_closing() && st_socket<Socket, Packer, Unpacker>::obsoleted();}
virtual bool obsoleted() {return !is_closing() && super::obsoleted();}
//reset all, be ensure that there's no any operations performed on this st_tcp_socket_base when invoke it
void reset() {reset_state(); close_state = 0; st_socket<Socket, Packer, Unpacker>::reset();}
void reset() {reset_state(); close_state = 0; super::reset();}
void reset_state()
{
unpacker_->reset_state();
st_socket<Socket, Packer, Unpacker>::reset_state();
super::reset_state();
}
bool is_closing() const {return 0 != close_state;}
......@@ -68,7 +66,7 @@ public:
boost::shared_ptr<const i_unpacker<out_msg_type> > inner_unpacker() const {return unpacker_;}
void inner_unpacker(const boost::shared_ptr<i_unpacker<out_msg_type> >& _unpacker_) {unpacker_ = _unpacker_;}
using st_socket<Socket, Packer, Unpacker>::send_msg;
using super::send_msg;
///////////////////////////////////////////////////
//msg sending interface
TCP_SEND_MSG(send_msg, false) //use the packer with native = false to pack the msgs
......@@ -122,7 +120,7 @@ protected:
ST_THIS sending = false;
else if (!ST_THIS sending && !ST_THIS send_msg_buffer.empty())
{
ST_THIS stat.send_delay_sum += st_socket<Socket, Packer, Unpacker>::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS stat.send_delay_sum += super::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS sending = true;
ST_THIS last_send_msg.swap(ST_THIS send_msg_buffer.front());
ST_THIS send_msg_buffer.pop_front();
......@@ -145,7 +143,7 @@ protected:
ST_THIS make_handler_error_size(boost::bind(&st_tcp_socket_base::recv_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
virtual bool is_send_allowed() const {return !is_closing() && st_socket<Socket, Packer, Unpacker>::is_send_allowed();}
virtual bool is_send_allowed() const {return !is_closing() && super::is_send_allowed();}
//can send data or not(just put into send buffer)
//msg can not be unpacked
......@@ -190,8 +188,8 @@ private:
ST_THIS stat.recv_byte_sum += (++iter).base()->size();
(++op_iter).base()->swap(*iter.base());
}
ST_THIS dispatch_msg();
}
ST_THIS dispatch_msg();
if (!unpack_ok)
{
......@@ -210,7 +208,7 @@ private:
{
assert(bytes_transferred == ST_THIS last_send_msg.size());
ST_THIS stat.send_time_sum += st_socket<Socket, Packer, Unpacker>::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_time_sum += super::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_byte_sum += bytes_transferred;
++ST_THIS stat.send_msg_sum;
#ifdef ST_ASIO_WANT_MSG_SEND_NOTIFY
......@@ -241,9 +239,6 @@ protected:
int close_state; //2-the first step of graceful close, 1-force close, 0-normal state
};
} //namespace st_tcp
} //namespace st_asio_wrapper
using namespace st_asio_wrapper::st_tcp; //compatible with old version which doesn't have st_tcp namespace.
} //namespace
#endif /* ST_ASIO_WRAPPER_TCP_SOCKET_H_ */
......@@ -19,18 +19,19 @@
namespace st_asio_wrapper
{
typedef st_sclient<st_udp_socket> st_udp_sclient;
template<typename Socket = st_udp_socket, typename Pool = st_object_pool<Socket> >
template<typename Socket, typename Pool = st_object_pool<Socket> >
class st_udp_client_base : public st_client<Socket, Pool>
{
protected:
typedef st_client<Socket, Pool> super;
public:
using st_client<Socket, Pool>::TIMER_BEGIN;
using st_client<Socket, Pool>::TIMER_END;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_udp_client_base(st_service_pump& service_pump_) : st_client<Socket, Pool>(service_pump_) {}
st_udp_client_base(st_service_pump& service_pump_) : super(service_pump_) {}
using st_client<Socket, Pool>::add_client;
using super::add_client;
typename Pool::object_type add_client(unsigned short port, const std::string& ip = std::string())
{
BOOST_AUTO(client_ptr, ST_THIS create_object());
......@@ -49,7 +50,6 @@ public:
protected:
virtual void uninit() {ST_THIS stop(); graceful_close();}
};
typedef st_udp_client_base<> st_udp_client;
} //namespace
......
......@@ -13,10 +13,7 @@
#ifndef ST_ASIO_WRAPPER_UDP_SOCKET_H_
#define ST_ASIO_WRAPPER_UDP_SOCKET_H_
#include <boost/array.hpp>
#include "st_asio_wrapper_socket.h"
#include "st_asio_wrapper_unpacker.h"
//in set_local_addr, if the IP is empty, ST_ASIO_UDP_DEFAULT_IP_VERSION will define the IP version,
//or, the IP version will be deduced by the IP address.
......@@ -25,18 +22,15 @@
#define ST_ASIO_UDP_DEFAULT_IP_VERSION boost::asio::ip::udp::v4()
#endif
#ifndef ST_ASIO_DEFAULT_UDP_UNPACKER
#define ST_ASIO_DEFAULT_UDP_UNPACKER udp_unpacker
#endif
namespace st_asio_wrapper
{
namespace st_udp
{
template <typename Packer = ST_ASIO_DEFAULT_PACKER, typename Unpacker = ST_ASIO_DEFAULT_UDP_UNPACKER, typename Socket = boost::asio::ip::udp::socket>
template <typename Packer, typename Unpacker, typename Socket = boost::asio::ip::udp::socket>
class st_udp_socket_base : public st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type> >
{
protected:
typedef st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type>> super;
public:
typedef udp_msg<typename Packer::msg_type> in_msg_type;
typedef const in_msg_type in_msg_ctype;
......@@ -44,10 +38,10 @@ public:
typedef const out_msg_type out_msg_ctype;
public:
using st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type> >::TIMER_BEGIN;
using st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type> >::TIMER_END;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_udp_socket_base(boost::asio::io_service& io_service_) : st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>(io_service_), unpacker_(boost::make_shared<Unpacker>()) {}
st_udp_socket_base(boost::asio::io_service& io_service_) : super(io_service_), unpacker_(boost::make_shared<Unpacker>()) {}
//reset all, be ensure that there's no any operations performed on this st_udp_socket when invoke it
//please note, when reuse this st_udp_socket, st_object_pool will invoke reset(), child must re-write this to initialize
......@@ -56,7 +50,7 @@ public:
virtual void reset()
{
reset_state();
st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::reset();
super::reset();
boost::system::error_code ec;
ST_THIS lowest_layer().open(local_addr.protocol(), ec); assert(!ec);
......@@ -71,7 +65,7 @@ public:
void reset_state()
{
unpacker_->reset_state();
st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::reset_state();
super::reset_state();
}
bool set_local_addr(unsigned short port, const std::string& ip = std::string())
......@@ -103,7 +97,7 @@ public:
boost::shared_ptr<const i_udp_unpacker<typename Unpacker::msg_type> > inner_unpacker() const {return unpacker_;}
void inner_unpacker(const boost::shared_ptr<i_udp_unpacker<typename Unpacker::msg_type> >& _unpacker_) {unpacker_ = _unpacker_;}
using st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::send_msg;
using super::send_msg;
///////////////////////////////////////////////////
//msg sending interface
UDP_SEND_MSG(send_msg, false) //use the packer with native = false to pack the msgs
......@@ -139,7 +133,7 @@ protected:
ST_THIS sending = false;
else if (!ST_THIS sending && !ST_THIS send_msg_buffer.empty())
{
ST_THIS stat.send_delay_sum += st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS stat.send_delay_sum += super::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS sending = true;
ST_THIS last_send_msg.swap(ST_THIS send_msg_buffer.front());
ST_THIS send_msg_buffer.pop_front();
......@@ -163,7 +157,7 @@ protected:
ST_THIS make_handler_error_size(boost::bind(&st_udp_socket_base::recv_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
virtual bool is_send_allowed() const {return ST_THIS lowest_layer().is_open() && st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::is_send_allowed();}
virtual bool is_send_allowed() const {return ST_THIS lowest_layer().is_open() && super::is_send_allowed();}
//can send data or not(just put into send buffer)
virtual void on_recv_error(const boost::system::error_code& ec)
......@@ -220,7 +214,7 @@ private:
{
assert(bytes_transferred == ST_THIS last_send_msg.size());
ST_THIS stat.send_time_sum += st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_time_sum += super::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_byte_sum += bytes_transferred;
++ST_THIS stat.send_msg_sum;
#ifdef ST_ASIO_WANT_MSG_SEND_NOTIFY
......@@ -253,11 +247,7 @@ protected:
boost::shared_mutex close_mutex;
};
typedef st_udp_socket_base<> st_udp_socket;
} //namespace st_udp
} //namespace st_asio_wrapper
using namespace st_asio_wrapper::st_udp; //compatible with old version which doesn't have st_udp namespace.
} //namespace
#endif /* ST_ASIO_WRAPPER_UDP_SOCKET_H_ */
......@@ -12,8 +12,9 @@
#define ST_ASIO_MSG_BUFFER_SIZE 65536
//configuration
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#ifdef _MSC_VER
#define atoll _atoi64
......@@ -106,7 +107,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: pingpong_client [service thread number=1] [<port=%d> [<ip=%s> [link num=16]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
printf("usage: pingpong_client [<service thread number=1> [<port=%d> [<ip=%s> [link num=16]]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
else
......
......@@ -9,8 +9,9 @@
#define ST_ASIO_MSG_BUFFER_SIZE 65536
//configuration
#include "../include/st_asio_wrapper_server.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#ifdef _MSC_VER
#define atoll _atoi64
......@@ -49,7 +50,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: pingpong_server [service thread number=1] [<port=%d> [ip=0.0.0.0]]\n", ST_ASIO_SERVER_PORT);
printf("usage: pingpong_server [<service thread number=1> [<port=%d> [ip=0.0.0.0]]]\n", ST_ASIO_SERVER_PORT);
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
else
......
......@@ -30,8 +30,9 @@
#define ST_ASIO_DEFAULT_UNPACKER prefix_suffix_unpacker
#endif
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......@@ -214,7 +215,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: test_client [service thread number=1] [<port=%d> [<ip=%s> [link num=16]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
printf("usage: test_client [<service thread number=1> [<port=%d> [<ip=%s> [link num=16]]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
else
......
......@@ -6,8 +6,9 @@
//#define ST_ASIO_DEFAULT_UDP_UNPACKER replaceable_udp_unpacker
//configuration
#include "../include/st_asio_wrapper_udp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......
......@@ -5,8 +5,9 @@
#include <boost/timer/timer.hpp>
#include "../file_server/packer_unpacker.h"
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#if BOOST_VERSION >= 105300
extern boost::atomic_ushort completed_client_num;
......
......@@ -11,6 +11,7 @@
#include "../include/st_asio_wrapper_server.h"
using namespace st_asio_wrapper;
#include "file_socket.h"
#define QUIT_COMMAND "quit"
......
......@@ -2,9 +2,9 @@
#ifndef FILE_SOCKET_H_
#define FILE_SOCKET_H_
#include "../include/st_asio_wrapper_server_socket.h"
using namespace st_asio_wrapper;
#include "packer_unpacker.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper::ext;
class file_socket : public base_socket, public st_server_socket
{
......
#ifndef PACKER_UNPACKER_H_
#define PACKER_UNPACKER_H_
#include "../include/st_asio_wrapper_packer.h"
#include "../include/st_asio_wrapper_unpacker.h"
#include "../include/st_asio_wrapper_base.h"
using namespace st_asio_wrapper;
#ifdef _MSC_VER
......
/*
* st_asio_wrapper_ext.h
*
* Created on: 2016-7-30
* Author: youngwolf
* email: mail2tao@163.com
* QQ: 676218192
* Community on QQ: 198941541
*
* extensional, replaceable and indispensable components.
*/
#ifndef ST_ASIO_WRAPPER_EXT_H_
#define ST_ASIO_WRAPPER_EXT_H_
#include "../st_asio_wrapper_base.h"
#include "../st_asio_wrapper_client.h"
#include "../st_asio_wrapper_tcp_client.h"
#include "../st_asio_wrapper_udp_client.h"
#include "../st_asio_wrapper_server.h"
#include "st_asio_wrapper_packer.h"
#include "st_asio_wrapper_unpacker.h"
#ifndef ST_ASIO_DEFAULT_PACKER
#define ST_ASIO_DEFAULT_PACKER packer
#endif
#ifndef ST_ASIO_DEFAULT_UNPACKER
#define ST_ASIO_DEFAULT_UNPACKER unpacker
#endif
#ifndef ST_ASIO_DEFAULT_UDP_UNPACKER
#define ST_ASIO_DEFAULT_UDP_UNPACKER udp_unpacker
#endif
namespace st_asio_wrapper { namespace ext {
typedef st_server_socket_base<ST_ASIO_DEFAULT_PACKER, ST_ASIO_DEFAULT_UNPACKER> st_server_socket;
typedef st_server_base<st_server_socket> st_server;
typedef st_connector_base<ST_ASIO_DEFAULT_PACKER, ST_ASIO_DEFAULT_UNPACKER> st_connector;
typedef st_sclient<st_connector> st_tcp_sclient;
typedef st_tcp_client_base<st_connector> st_tcp_client;
typedef st_udp_socket_base<ST_ASIO_DEFAULT_PACKER, ST_ASIO_DEFAULT_UDP_UNPACKER> st_udp_socket;
typedef st_sclient<st_udp_socket> st_udp_sclient;
typedef st_udp_client_base<st_udp_socket> st_udp_client;
}} //namespace
#endif /* ST_ASIO_WRAPPER_EXT_H_ */
......@@ -13,7 +13,7 @@
#ifndef ST_ASIO_WRAPPER_PACKER_H_
#define ST_ASIO_WRAPPER_PACKER_H_
#include "st_asio_wrapper_base.h"
#include "../st_asio_wrapper_base.h"
#ifdef ST_ASIO_HUGE_MSG
#define ST_ASIO_HEAD_TYPE uint32_t
......@@ -24,8 +24,7 @@
#endif
#define ST_ASIO_HEAD_LEN (sizeof(ST_ASIO_HEAD_TYPE))
namespace st_asio_wrapper
{
namespace st_asio_wrapper { namespace ext {
class packer_helper
{
......@@ -54,27 +53,6 @@ public:
}
};
template<typename MsgType>
class i_packer
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
protected:
virtual ~i_packer() {}
public:
virtual void reset_state() {}
virtual msg_type pack_msg(const char* const pstr[], const size_t len[], size_t num, bool native = false) = 0;
virtual char* raw_data(msg_type& msg) const {return nullptr;}
virtual const char* raw_data(msg_ctype& msg) const {return nullptr;}
virtual size_t raw_data_len(msg_ctype& msg) const {return 0;}
msg_type pack_msg(const char* pstr, size_t len, bool native = false) {return pack_msg(&pstr, &len, 1, native);}
msg_type pack_msg(const std::string& str, bool native = false) {return pack_msg(str.data(), str.size(), native);}
};
class packer : public i_packer<std::string>
{
public:
......@@ -121,6 +99,15 @@ public:
class replaceable_packer : public i_packer<replaceable_buffer>
{
public:
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
public:
using i_packer<msg_type>::pack_msg;
virtual msg_type pack_msg(const char* const pstr[], const size_t len[], size_t num, bool native = false)
......@@ -177,6 +164,6 @@ private:
std::string _prefix, _suffix;
};
} //namespace
}} //namespace
#endif /* ST_ASIO_WRAPPER_PACKER_H_ */
......@@ -14,9 +14,8 @@
#define ST_ASIO_WRAPPER_UNPACKER_H_
#include <boost/array.hpp>
#include <boost/container/list.hpp>
#include "st_asio_wrapper_base.h"
#include "../st_asio_wrapper_base.h"
#ifdef ST_ASIO_HUGE_MSG
#define ST_ASIO_HEAD_TYPE uint32_t
......@@ -27,56 +26,7 @@
#endif
#define ST_ASIO_HEAD_LEN (sizeof(ST_ASIO_HEAD_TYPE))
namespace st_asio_wrapper
{
template<typename MsgType>
class i_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<msg_type> container_type;
protected:
virtual ~i_unpacker() {}
public:
virtual void reset_state() = 0;
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can) = 0;
virtual size_t completion_condition(const boost::system::error_code& ec, size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
template<typename MsgType>
class udp_msg : public MsgType
{
public:
boost::asio::ip::udp::endpoint peer_addr;
udp_msg() {}
udp_msg(const boost::asio::ip::udp::endpoint& _peer_addr, MsgType&& msg) : MsgType(std::move(msg)), peer_addr(_peer_addr) {}
void swap(udp_msg& other) {std::swap(peer_addr, other.peer_addr); MsgType::swap(other);}
void swap(boost::asio::ip::udp::endpoint& addr, MsgType&& tmp_msg) {std::swap(peer_addr, addr); MsgType::swap(tmp_msg);}
};
template<typename MsgType>
class i_udp_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<udp_msg<msg_type>> container_type;
protected:
virtual ~i_udp_unpacker() {}
public:
virtual void reset_state() {}
virtual msg_type parse_msg(size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
namespace st_asio_wrapper { namespace ext {
class unpacker : public i_unpacker<std::string>
{
......@@ -191,6 +141,15 @@ protected:
class replaceable_unpacker : public i_unpacker<replaceable_buffer>
{
public:
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
public:
virtual void reset_state() {unpacker_.reset_state();}
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can)
......@@ -217,6 +176,15 @@ protected:
class replaceable_udp_unpacker : public i_udp_unpacker<replaceable_buffer>
{
public:
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
public:
virtual msg_type parse_msg(size_t bytes_transferred)
{
......@@ -231,15 +199,43 @@ protected:
boost::array<char, ST_ASIO_MSG_BUFFER_SIZE> raw_buff;
};
//this unpacker demonstrate how to forbid memory copy while parsing msgs.
class unbuffered_unpacker : public i_unpacker<inflexible_buffer>
class most_primitive_buffer
{
public:
unbuffered_unpacker() {reset_state();}
most_primitive_buffer() {do_detach();}
most_primitive_buffer(most_primitive_buffer&& other) {do_attach(other.buff, other.len); other.do_detach();}
~most_primitive_buffer() {free();}
void assign(size_t _len) {free(); do_attach(new char[_len], _len);}
void free() {delete buff; do_detach();}
//the following five functions (char* data() is used by unpackers, not counted in) are needed by st_asio_wrapper,
//for other functions, depends on the implementation of your packer and unpacker.
bool empty() const {return 0 == len || nullptr == buff;}
size_t size() const {return len;}
const char* data() const {return buff;}
char* data() {return buff;}
void swap(most_primitive_buffer& other) {std::swap(buff, other.buff); std::swap(len, other.len);}
void clear() {free();}
protected:
void do_attach(char* _buff, size_t _len) {buff = _buff; len = _len;}
void do_detach() {buff = nullptr; len = 0;}
protected:
char* buff;
size_t len;
};
//this unpacker demonstrate how to forbid memory copying while parsing msgs (let asio write msg directly).
class buffer_free_unpacker : public i_unpacker<most_primitive_buffer>
{
public:
buffer_free_unpacker() {reset_state();}
size_t current_msg_length() const {return raw_buff.size();} //current msg's total length(not include the head), 0 means don't know
public:
virtual void reset_state() {raw_buff.detach(); step = 0;}
virtual void reset_state() {raw_buff.clear(); step = 0;}
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can)
{
if (0 == step) //the head been received
......@@ -277,7 +273,16 @@ public:
if (0 == step) //want the head
{
assert(raw_buff.empty());
return boost::asio::detail::default_max_transfer_size;
if (bytes_transferred < ST_ASIO_HEAD_LEN)
return boost::asio::detail::default_max_transfer_size;
assert(ST_ASIO_HEAD_LEN == bytes_transferred);
auto cur_msg_len = ST_ASIO_HEAD_N2H(head) - ST_ASIO_HEAD_LEN;
if (cur_msg_len > ST_ASIO_MSG_BUFFER_SIZE - ST_ASIO_HEAD_LEN) //invalid msg, stop reading
step = -1;
else
raw_buff.assign(cur_msg_len);
}
else if (1 == step) //want the body
{
......@@ -501,6 +506,6 @@ protected:
boost::array<char, ST_ASIO_MSG_BUFFER_SIZE> raw_buff;
};
} //namespace
}} //namespace
#endif /* ST_ASIO_WRAPPER_UNPACKER_H_ */
......@@ -24,17 +24,20 @@
* 2016.7.17 version 1.0.1
* Support boost-1.49, it's the minimum version for st_asio_wrapper because of boost::container.
*
* 2016.9.4 version 1.0.2
* Fix bug: if receive buffer overflow and on_msg() returns false (which means using receive buffer),
* st_socket will call on_msg() again and again (asynchronously) for the same msg until receive buffer becomes available.
* 2016.x.xx version 1.1.0
* Add stream_unpacker to receive native data.
* asio_server and test_client are now able to start with configurable thread number.
* Add efficiency statistic for performance tuning, and it can be shut down.
* Add pingpong test.
* Move packers and unpackers out of 'include' directory (now in 'ext' directory), they don't belong to st_asio_wrapper library.
*
*/
#ifndef ST_ASIO_WRAPPER_H_
#define ST_ASIO_WRAPPER_H_
#define ST_ASIO_WRAPPER_VER 10002 //[x]xyyzz -> [x]x.[y]y.[z]z
#define ST_ASIO_WRAPPER_VERSION "1.0.2"
#define ST_ASIO_WRAPPER_VER 10100 //[x]xyyzz -> [x]x.[y]y.[z]z
#define ST_ASIO_WRAPPER_VERSION "1.1.0"
#ifdef _MSC_VER
static_assert(_MSC_VER >= 1600, "st_asio_wrapper must be compiled with Visual C++ 10.0 or higher.");
......
......@@ -24,6 +24,7 @@
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/smart_ptr.hpp>
#include <boost/container/list.hpp>
#include "st_asio_wrapper.h"
......@@ -35,7 +36,7 @@
#define ST_ASIO_MSG_BUFFER_SIZE 4000
#endif
static_assert(ST_ASIO_MSG_BUFFER_SIZE > 0, "message buffer size must be bigger than zero.");
//msg send and recv buffer's maximum size (list::size()), corresponding buffers are expanded dynamicly, which means only allocate memory when needed.
//msg send and recv buffer's maximum size (list::size()), corresponding buffers are expanded dynamically, which means only allocate memory when needed.
#ifndef ST_ASIO_MAX_MSG_NUM
#define ST_ASIO_MAX_MSG_NUM 1024
#endif
......@@ -63,14 +64,7 @@ namespace st_asio_wrapper
virtual const char* data() const = 0;
};
class buffer : public std::string, public i_buffer
{
public:
virtual bool empty() const {return std::string::empty();}
virtual size_t size() const {return std::string::size();}
virtual const char* data() const {return std::string::data();}
};
//if you want to replace packer or unpacker at runtime, please use this as the msg type
class replaceable_buffer
{
public:
......@@ -94,44 +88,78 @@ namespace st_asio_wrapper
boost::shared_ptr<i_buffer> buffer;
};
//this buffer is more efficient than std::string if the memory is already allocated, because the replication been saved.
//for example, you are sending memory-mapped files.
class inflexible_buffer
//packer concept
template<typename MsgType>
class i_packer
{
public:
inflexible_buffer() {do_detach();}
inflexible_buffer(inflexible_buffer&& other) {do_attach(other.buff, other.len); other.do_detach();}
~inflexible_buffer() {detach();}
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
void assign(const char* _buff, size_t _len)
{
assert(_len > 0 && nullptr != _buff);
auto _buff_ = new char[_len];
memcpy(_buff_, _buff, _len);
attach(_buff_, _len);
}
protected:
virtual ~i_packer() {}
void attach(char* _buff, size_t _len) {detach(); do_attach(_buff, _len);}
void detach() {delete buff; do_detach();}
public:
virtual void reset_state() {}
virtual msg_type pack_msg(const char* const pstr[], const size_t len[], size_t num, bool native = false) = 0;
virtual char* raw_data(msg_type& msg) const {return nullptr;}
virtual const char* raw_data(msg_ctype& msg) const {return nullptr;}
virtual size_t raw_data_len(msg_ctype& msg) const {return 0;}
msg_type pack_msg(const char* pstr, size_t len, bool native = false) {return pack_msg(&pstr, &len, 1, native);}
msg_type pack_msg(const std::string& str, bool native = false) {return pack_msg(str.data(), str.size(), native);}
};
//packer concept
//the following five functions (char* data() is used by inflexible_unpacker, not counted) are needed by st_asio_wrapper,
//for other functions, depends on the implementation of your packer and unpacker.
bool empty() const {return 0 == len || nullptr == buff;}
size_t size() const {return len;}
const char* data() const {return buff;}
char* data() {return buff;}
void swap(inflexible_buffer& other) {std::swap(buff, other.buff); std::swap(len, other.len);}
void clear() {detach();}
//unpacker concept
template<typename MsgType>
class i_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<msg_type> container_type;
protected:
void do_attach(char* _buff, size_t _len) {buff = _buff; len = _len;}
void do_detach() {buff = nullptr; len = 0;}
virtual ~i_unpacker() {}
public:
virtual void reset_state() = 0;
virtual bool parse_msg(size_t bytes_transferred, container_type& msg_can) = 0;
virtual size_t completion_condition(const boost::system::error_code& ec, size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
template<typename MsgType>
class udp_msg : public MsgType
{
public:
boost::asio::ip::udp::endpoint peer_addr;
udp_msg() {}
udp_msg(const boost::asio::ip::udp::endpoint& _peer_addr, MsgType&& msg) : MsgType(std::move(msg)), peer_addr(_peer_addr) {}
void swap(udp_msg& other) {std::swap(peer_addr, other.peer_addr); MsgType::swap(other);}
void swap(boost::asio::ip::udp::endpoint& addr, MsgType&& tmp_msg) {std::swap(peer_addr, addr); MsgType::swap(tmp_msg);}
};
template<typename MsgType>
class i_udp_unpacker
{
public:
typedef MsgType msg_type;
typedef const msg_type msg_ctype;
typedef boost::container::list<udp_msg<msg_type>> container_type;
protected:
char* buff;
size_t len;
virtual ~i_udp_unpacker() {}
public:
virtual void reset_state() {}
virtual msg_type parse_msg(size_t bytes_transferred) = 0;
virtual boost::asio::mutable_buffers_1 prepare_next_recv() = 0;
};
//unpacker concept
//free functions, used to do something to any container(except map and multimap) optionally with any mutex
#if !defined _MSC_VER || _MSC_VER >= 1700
......
......@@ -30,27 +30,30 @@ static_assert(ST_ASIO_RECONNECT_INTERVAL >= 0, "reconnect interval must be bigge
namespace st_asio_wrapper
{
template <typename Packer = ST_ASIO_DEFAULT_PACKER, typename Unpacker = ST_ASIO_DEFAULT_UNPACKER, typename Socket = boost::asio::ip::tcp::socket>
template <typename Packer, typename Unpacker, typename Socket = boost::asio::ip::tcp::socket>
class st_connector_base : public st_tcp_socket_base<Socket, Packer, Unpacker>
{
protected:
typedef st_tcp_socket_base<Socket, Packer, Unpacker> super;
public:
static const unsigned char TIMER_BEGIN = st_tcp_socket_base<Socket, Packer, Unpacker>::TIMER_END;
static const unsigned char TIMER_BEGIN = super::TIMER_END;
static const unsigned char TIMER_CONNECT = TIMER_BEGIN;
static const unsigned char TIMER_ASYNC_CLOSE = TIMER_BEGIN + 1;
static const unsigned char TIMER_END = TIMER_BEGIN + 10;
st_connector_base(boost::asio::io_service& io_service_) : st_tcp_socket_base<Socket, Packer, Unpacker>(io_service_), connected(false), reconnecting(true)
st_connector_base(boost::asio::io_service& io_service_) : super(io_service_), connected(false), reconnecting(true)
{set_server_addr(ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);}
template<typename Arg>
st_connector_base(boost::asio::io_service& io_service_, Arg& arg) : st_tcp_socket_base<Socket, Packer, Unpacker>(io_service_, arg), connected(false), reconnecting(true)
st_connector_base(boost::asio::io_service& io_service_, Arg& arg) : super(io_service_, arg), connected(false), reconnecting(true)
{set_server_addr(ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);}
//reset all, be ensure that there's no any operations performed on this st_connector_base when invoke it
//notice, when reusing this st_connector_base, st_object_pool will invoke reset(), child must re-write this to initialize
//all member variables, and then do not forget to invoke st_connector_base::reset() to initialize father's member variables
virtual void reset() {connected = false; reconnecting = true; st_tcp_socket_base<Socket, Packer, Unpacker>::reset();}
virtual bool obsoleted() {return !reconnecting && st_tcp_socket_base<Socket, Packer, Unpacker>::obsoleted();}
virtual void reset() {connected = false; reconnecting = true; super::reset();}
virtual bool obsoleted() {return !reconnecting && super::obsoleted();}
bool set_server_addr(unsigned short port, const std::string& ip = ST_ASIO_SERVER_IP)
{
......@@ -77,7 +80,7 @@ public:
connected = false;
}
st_tcp_socket_base<Socket, Packer, Unpacker>::force_close();
super::force_close();
}
//sync must be false if you call graceful_close in on_msg
......@@ -92,7 +95,7 @@ public:
reconnecting = reconnect;
connected = false;
if (st_tcp_socket_base<Socket, Packer, Unpacker>::graceful_close(sync))
if (super::graceful_close(sync))
ST_THIS set_timer(TIMER_ASYNC_CLOSE, 10, boost::bind(&st_connector_base::async_close_handler, this, _1, ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION * 100));
}
......@@ -131,7 +134,7 @@ protected:
//after how much time(ms), st_connector will try to reconnect to the server, negative means give up.
virtual int prepare_reconnect(const boost::system::error_code& ec) {return ST_ASIO_RECONNECT_INTERVAL;}
virtual void on_connect() {unified_out::info_out("connecting success.");}
virtual bool is_send_allowed() const {return is_connected() && st_tcp_socket_base<Socket, Packer, Unpacker>::is_send_allowed();}
virtual bool is_send_allowed() const {return is_connected() && super::is_send_allowed();}
virtual void on_unpack_error() {unified_out::info_out("can not unpack msg."); force_close();}
virtual void on_recv_error(const boost::system::error_code& ec)
{
......@@ -209,7 +212,6 @@ protected:
bool connected;
bool reconnecting;
};
typedef st_connector_base<> st_connector;
} //namespace
......
......@@ -35,7 +35,7 @@ static_assert(ST_ASIO_ASYNC_ACCEPT_NUM > 0, "async accept number must be bigger
namespace st_asio_wrapper
{
template<typename Socket = st_server_socket, typename Pool = st_object_pool<Socket>, typename Server = i_server>
template<typename Socket, typename Pool = st_object_pool<Socket>, typename Server = i_server>
class st_server_base : public Server, public Pool
{
public:
......@@ -154,7 +154,6 @@ protected:
boost::asio::ip::tcp::endpoint server_addr;
boost::asio::ip::tcp::acceptor acceptor;
};
typedef st_server_base<> st_server;
} //namespace
......
......@@ -27,22 +27,25 @@ public:
virtual bool del_client(const boost::shared_ptr<st_timer>& client_ptr) = 0;
};
template<typename Packer = ST_ASIO_DEFAULT_PACKER, typename Unpacker = ST_ASIO_DEFAULT_UNPACKER, typename Server = i_server, typename Socket = boost::asio::ip::tcp::socket>
template<typename Packer, typename Unpacker, typename Server = i_server, typename Socket = boost::asio::ip::tcp::socket>
class st_server_socket_base : public st_tcp_socket_base<Socket, Packer, Unpacker>, public boost::enable_shared_from_this<st_server_socket_base<Packer, Unpacker, Server, Socket>>
{
protected:
typedef st_tcp_socket_base<Socket, Packer, Unpacker> super;
public:
static const unsigned char TIMER_BEGIN = st_tcp_socket_base<Socket, Packer, Unpacker>::TIMER_END;
static const unsigned char TIMER_BEGIN = super::TIMER_END;
static const unsigned char TIMER_ASYNC_CLOSE = TIMER_BEGIN;
static const unsigned char TIMER_END = TIMER_BEGIN + 10;
st_server_socket_base(Server& server_) : st_tcp_socket_base<Socket, Packer, Unpacker>(server_.get_service_pump()), server(server_) {}
st_server_socket_base(Server& server_) : super(server_.get_service_pump()), server(server_) {}
template<typename Arg>
st_server_socket_base(Server& server_, Arg& arg) : st_tcp_socket_base<Socket, Packer, Unpacker>(server_.get_service_pump(), arg), server(server_) {}
st_server_socket_base(Server& server_, Arg& arg) : super(server_.get_service_pump(), arg), server(server_) {}
//reset all, be ensure that there's no any operations performed on this socket when invoke it
//please note, when reuse this socket, st_object_pool will invoke reset(), child must re-write it to initialize all member variables,
//and then do not forget to invoke st_server_socket_base::reset() to initialize father's member variables
virtual void reset() {st_tcp_socket_base<Socket, Packer, Unpacker>::reset();}
virtual void reset() {super::reset();}
void disconnect() {force_close();}
void force_close()
......@@ -50,7 +53,7 @@ public:
if (1 != ST_THIS close_state)
show_info("server link:", "been closed.");
st_tcp_socket_base<Socket, Packer, Unpacker>::force_close();
super::force_close();
}
void graceful_close(bool sync = true)
......@@ -58,7 +61,7 @@ public:
if (!ST_THIS is_closing())
show_info("server link:", "been closing gracefully.");
if (st_tcp_socket_base<Socket, Packer, Unpacker>::graceful_close(sync))
if (super::graceful_close(sync))
ST_THIS set_timer(TIMER_ASYNC_CLOSE, 10, boost::bind(&st_server_socket_base::async_close_handler, this, _1, ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION * 100));
}
......@@ -131,7 +134,6 @@ private:
protected:
Server& server;
};
typedef st_server_socket_base<> st_server_socket;
} //namespace
......
......@@ -18,17 +18,13 @@
#include <boost/date_time.hpp>
#include <boost/container/list.hpp>
#include "st_asio_wrapper_packer.h"
#include "st_asio_wrapper_base.h"
#include "st_asio_wrapper_timer.h"
#ifndef ST_ASIO_DEFAULT_PACKER
#define ST_ASIO_DEFAULT_PACKER packer
#endif
namespace st_asio_wrapper
{
template<typename Socket, typename Packer, typename Unpacker, typename InMsgType = typename Packer::msg_type, typename OutMsgType = typename Unpacker::msg_type>
template<typename Socket, typename Packer, typename Unpacker, typename InMsgType, typename OutMsgType>
class st_socket: public st_timer
{
public:
......@@ -349,45 +345,32 @@ protected:
//call this in recv_handler (in subclasses) only
void dispatch_msg()
{
auto overflow = false;
#ifndef ST_ASIO_FORCE_TO_USE_MSG_RECV_BUFFER
out_container_type temp_2_msg_buffer;
auto begin_time = statistic::local_time();
for (auto iter = std::begin(temp_msg_buffer); !suspend_dispatch_msg_ && !posting && iter != std::end(temp_msg_buffer);)
if (on_msg(*iter))
temp_msg_buffer.erase(iter++);
else
temp_2_msg_buffer.splice(std::end(temp_2_msg_buffer), temp_msg_buffer, iter++);
auto time_duration = statistic::local_time() - begin_time;
stat.handle_time_1_sum += time_duration;
stat.recv_idle_sum += time_duration;
if (!temp_2_msg_buffer.empty())
if (!temp_msg_buffer.empty())
{
#ifndef ST_ASIO_FORCE_TO_USE_MSG_RECV_BUFFER
out_container_type temp_2_msg_buffer;
auto begin_time = statistic::local_time();
for (auto iter = std::begin(temp_msg_buffer); !suspend_dispatch_msg_ && !posting && iter != std::end(temp_msg_buffer);)
if (on_msg(*iter))
temp_msg_buffer.erase(iter++);
else
temp_2_msg_buffer.splice(std::end(temp_2_msg_buffer), temp_msg_buffer, iter++);
auto time_duration = statistic::local_time() - begin_time;
stat.handle_time_1_sum += time_duration;
stat.recv_idle_sum += time_duration;
if (!temp_2_msg_buffer.empty())
{
boost::unique_lock<boost::shared_mutex> lock(recv_msg_buffer_mutex);
if (splice_helper(recv_msg_buffer, temp_2_msg_buffer))
do_dispatch_msg(false);
}
temp_msg_buffer.splice(std::begin(temp_msg_buffer), temp_2_msg_buffer);
#else
boost::unique_lock<boost::shared_mutex> lock(recv_msg_buffer_mutex);
if (splice_helper(recv_msg_buffer, temp_2_msg_buffer))
if (splice_helper(recv_msg_buffer, temp_msg_buffer))
do_dispatch_msg(false);
}
temp_msg_buffer.splice(std::begin(temp_msg_buffer), temp_2_msg_buffer);
#else
if (!temp_msg_buffer.empty())
{
if (suspend_dispatch_msg_ || posting)
overflow = true;
else
for (auto iter = std::begin(temp_msg_buffer); iter != std::end(temp_msg_buffer);)
if (on_msg(*iter))
temp_msg_buffer.erase(iter++);
else
++iter;
}
#endif
if (!overflow)
{
boost::unique_lock<boost::shared_mutex> lock(recv_msg_buffer_mutex);
recv_msg_buffer.splice(std::end(recv_msg_buffer), temp_msg_buffer);
overflow = recv_msg_buffer.size() > ST_ASIO_MAX_MSG_NUM;
do_dispatch_msg(false);
}
if (!overflow)
......
......@@ -19,18 +19,18 @@
namespace st_asio_wrapper
{
typedef st_sclient<st_connector> st_tcp_sclient;
template<typename Socket = st_connector, typename Pool = st_object_pool<Socket>>
template<typename Socket, typename Pool = st_object_pool<Socket>>
class st_tcp_client_base : public st_client<Socket, Pool>
{
protected:
typedef st_client<Socket, Pool> super;
public:
using st_client<Socket, Pool>::TIMER_BEGIN;
using st_client<Socket, Pool>::TIMER_END;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_tcp_client_base(st_service_pump& service_pump_) : st_client<Socket, Pool>(service_pump_) {}
st_tcp_client_base(st_service_pump& service_pump_) : super(service_pump_) {}
template<typename Arg>
st_tcp_client_base(st_service_pump& service_pump_, Arg arg) : st_client<Socket, Pool>(service_pump_, arg) {}
st_tcp_client_base(st_service_pump& service_pump_, Arg arg) : super(service_pump_, arg) {}
//connected link size, may smaller than total object size(st_object_pool::size)
size_t valid_size()
......@@ -43,7 +43,7 @@ public:
return size;
}
using st_client<Socket, Pool>::add_client;
using super::add_client;
typename Pool::object_type add_client()
{
auto client_ptr(ST_THIS create_object());
......@@ -79,7 +79,6 @@ public:
protected:
virtual void uninit() {ST_THIS stop(); graceful_close();}
};
typedef st_tcp_client_base<> st_tcp_client;
} //namespace
......
......@@ -14,24 +14,17 @@
#define ST_ASIO_WRAPPER_TCP_SOCKET_H_
#include "st_asio_wrapper_socket.h"
#include "st_asio_wrapper_unpacker.h"
#ifndef ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION
#define ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION 5 //seconds, maximum waiting seconds while graceful closing
#endif
static_assert(ST_ASIO_GRACEFUL_CLOSE_MAX_DURATION > 0, "graceful close duration must be bigger than zero.");
#ifndef ST_ASIO_DEFAULT_UNPACKER
#define ST_ASIO_DEFAULT_UNPACKER unpacker
#endif
namespace st_asio_wrapper
{
namespace st_tcp
{
template <typename Socket, typename Packer, typename Unpacker>
class st_tcp_socket_base : public st_socket<Socket, Packer, Unpacker>
class st_tcp_socket_base : public st_socket<Socket, Packer, Unpacker, typename Packer::msg_type, typename Unpacker::msg_type>
{
public:
typedef typename Packer::msg_type in_msg_type;
......@@ -40,22 +33,23 @@ public:
typedef typename Unpacker::msg_ctype out_msg_ctype;
protected:
using st_socket<Socket, Packer, Unpacker>::TIMER_BEGIN;
using st_socket<Socket, Packer, Unpacker>::TIMER_END;
typedef st_socket<Socket, Packer, Unpacker, typename Packer::msg_type, typename Unpacker::msg_type> super;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_tcp_socket_base(boost::asio::io_service& io_service_) : st_socket<Socket, Packer, Unpacker>(io_service_), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
st_tcp_socket_base(boost::asio::io_service& io_service_) : super(io_service_), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
template<typename Arg>
st_tcp_socket_base(boost::asio::io_service& io_service_, Arg& arg) : st_socket<Socket, Packer, Unpacker>(io_service_, arg), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
st_tcp_socket_base(boost::asio::io_service& io_service_, Arg& arg) : super(io_service_, arg), unpacker_(boost::make_shared<Unpacker>()), close_state(0) {}
public:
virtual bool obsoleted() {return !is_closing() && st_socket<Socket, Packer, Unpacker>::obsoleted();}
virtual bool obsoleted() {return !is_closing() && super::obsoleted();}
//reset all, be ensure that there's no any operations performed on this st_tcp_socket_base when invoke it
void reset() {reset_state(); close_state = 0; st_socket<Socket, Packer, Unpacker>::reset();}
void reset() {reset_state(); close_state = 0; super::reset();}
void reset_state()
{
unpacker_->reset_state();
st_socket<Socket, Packer, Unpacker>::reset_state();
super::reset_state();
}
bool is_closing() const {return 0 != close_state;}
......@@ -67,7 +61,7 @@ public:
boost::shared_ptr<const i_unpacker<out_msg_type>> inner_unpacker() const {return unpacker_;}
void inner_unpacker(const boost::shared_ptr<i_unpacker<out_msg_type>>& _unpacker_) {unpacker_ = _unpacker_;}
using st_socket<Socket, Packer, Unpacker>::send_msg;
using super::send_msg;
///////////////////////////////////////////////////
//msg sending interface
TCP_SEND_MSG(send_msg, false) //use the packer with native = false to pack the msgs
......@@ -121,7 +115,7 @@ protected:
ST_THIS sending = false;
else if (!ST_THIS sending && !ST_THIS send_msg_buffer.empty())
{
ST_THIS stat.send_delay_sum += st_socket<Socket, Packer, Unpacker>::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS stat.send_delay_sum += super::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS sending = true;
ST_THIS last_send_msg.swap(ST_THIS send_msg_buffer.front());
ST_THIS send_msg_buffer.pop_front();
......@@ -144,7 +138,7 @@ protected:
ST_THIS make_handler_error_size(boost::bind(&st_tcp_socket_base::recv_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
virtual bool is_send_allowed() const {return !is_closing() && st_socket<Socket, Packer, Unpacker>::is_send_allowed();}
virtual bool is_send_allowed() const {return !is_closing() && super::is_send_allowed();}
//can send data or not(just put into send buffer)
//msg can not be unpacked
......@@ -189,8 +183,8 @@ private:
ST_THIS stat.recv_byte_sum += (++iter).base()->size();
(++op_iter).base()->swap(*iter.base());
}
ST_THIS dispatch_msg();
}
ST_THIS dispatch_msg();
if (!unpack_ok)
{
......@@ -209,7 +203,7 @@ private:
{
assert(bytes_transferred == ST_THIS last_send_msg.size());
ST_THIS stat.send_time_sum += st_socket<Socket, Packer, Unpacker>::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_time_sum += super::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_byte_sum += bytes_transferred;
++ST_THIS stat.send_msg_sum;
#ifdef ST_ASIO_WANT_MSG_SEND_NOTIFY
......@@ -240,9 +234,6 @@ protected:
int close_state; //2-the first step of graceful close, 1-force close, 0-normal state
};
} //namespace st_tcp
} //namespace st_asio_wrapper
using namespace st_asio_wrapper::st_tcp; //compatible with old version which doesn't have st_tcp namespace.
} //namespace
#endif /* ST_ASIO_WRAPPER_TCP_SOCKET_H_ */
......@@ -19,18 +19,19 @@
namespace st_asio_wrapper
{
typedef st_sclient<st_udp_socket> st_udp_sclient;
template<typename Socket = st_udp_socket, typename Pool = st_object_pool<Socket>>
template<typename Socket, typename Pool = st_object_pool<Socket>>
class st_udp_client_base : public st_client<Socket, Pool>
{
protected:
typedef st_client<Socket, Pool> super;
public:
using st_client<Socket, Pool>::TIMER_BEGIN;
using st_client<Socket, Pool>::TIMER_END;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_udp_client_base(st_service_pump& service_pump_) : st_client<Socket, Pool>(service_pump_) {}
st_udp_client_base(st_service_pump& service_pump_) : super(service_pump_) {}
using st_client<Socket, Pool>::add_client;
using super::add_client;
typename Pool::object_type add_client(unsigned short port, const std::string& ip = std::string())
{
auto client_ptr(ST_THIS create_object());
......@@ -49,7 +50,6 @@ public:
protected:
virtual void uninit() {ST_THIS stop(); graceful_close();}
};
typedef st_udp_client_base<> st_udp_client;
} //namespace
......
......@@ -13,10 +13,7 @@
#ifndef ST_ASIO_WRAPPER_UDP_SOCKET_H_
#define ST_ASIO_WRAPPER_UDP_SOCKET_H_
#include <boost/array.hpp>
#include "st_asio_wrapper_socket.h"
#include "st_asio_wrapper_unpacker.h"
//in set_local_addr, if the IP is empty, ST_ASIO_UDP_DEFAULT_IP_VERSION will define the IP version,
//or, the IP version will be deduced by the IP address.
......@@ -25,18 +22,15 @@
#define ST_ASIO_UDP_DEFAULT_IP_VERSION boost::asio::ip::udp::v4()
#endif
#ifndef ST_ASIO_DEFAULT_UDP_UNPACKER
#define ST_ASIO_DEFAULT_UDP_UNPACKER udp_unpacker
#endif
namespace st_asio_wrapper
{
namespace st_udp
{
template <typename Packer = ST_ASIO_DEFAULT_PACKER, typename Unpacker = ST_ASIO_DEFAULT_UDP_UNPACKER, typename Socket = boost::asio::ip::udp::socket>
template <typename Packer, typename Unpacker, typename Socket = boost::asio::ip::udp::socket>
class st_udp_socket_base : public st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type>>
{
protected:
typedef st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type>> super;
public:
typedef udp_msg<typename Packer::msg_type> in_msg_type;
typedef const in_msg_type in_msg_ctype;
......@@ -44,10 +38,10 @@ public:
typedef const out_msg_type out_msg_ctype;
public:
using st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type>>::TIMER_BEGIN;
using st_socket<Socket, Packer, Unpacker, udp_msg<typename Packer::msg_type>, udp_msg<typename Unpacker::msg_type>>::TIMER_END;
using super::TIMER_BEGIN;
using super::TIMER_END;
st_udp_socket_base(boost::asio::io_service& io_service_) : st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>(io_service_), unpacker_(boost::make_shared<Unpacker>()) {}
st_udp_socket_base(boost::asio::io_service& io_service_) : super(io_service_), unpacker_(boost::make_shared<Unpacker>()) {}
//reset all, be ensure that there's no any operations performed on this st_udp_socket when invoke it
//please note, when reuse this st_udp_socket, st_object_pool will invoke reset(), child must re-write this to initialize
......@@ -56,7 +50,7 @@ public:
virtual void reset()
{
reset_state();
st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::reset();
super::reset();
boost::system::error_code ec;
ST_THIS lowest_layer().open(local_addr.protocol(), ec); assert(!ec);
......@@ -71,7 +65,7 @@ public:
void reset_state()
{
unpacker_->reset_state();
st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::reset_state();
super::reset_state();
}
bool set_local_addr(unsigned short port, const std::string& ip = std::string())
......@@ -103,7 +97,7 @@ public:
boost::shared_ptr<const i_udp_unpacker<typename Unpacker::msg_type>> inner_unpacker() const {return unpacker_;}
void inner_unpacker(const boost::shared_ptr<i_udp_unpacker<typename Unpacker::msg_type>>& _unpacker_) {unpacker_ = _unpacker_;}
using st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::send_msg;
using super::send_msg;
///////////////////////////////////////////////////
//msg sending interface
UDP_SEND_MSG(send_msg, false) //use the packer with native = false to pack the msgs
......@@ -139,7 +133,7 @@ protected:
ST_THIS sending = false;
else if (!ST_THIS sending && !ST_THIS send_msg_buffer.empty())
{
ST_THIS stat.send_delay_sum += st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS stat.send_delay_sum += super::statistic::local_time() - ST_THIS send_msg_buffer.front().begin_time;
ST_THIS sending = true;
ST_THIS last_send_msg.swap(ST_THIS send_msg_buffer.front());
ST_THIS send_msg_buffer.pop_front();
......@@ -163,7 +157,7 @@ protected:
ST_THIS make_handler_error_size(boost::bind(&st_udp_socket_base::recv_handler, this, boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)));
}
virtual bool is_send_allowed() const {return ST_THIS lowest_layer().is_open() && st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::is_send_allowed();}
virtual bool is_send_allowed() const {return ST_THIS lowest_layer().is_open() && super::is_send_allowed();}
//can send data or not(just put into send buffer)
virtual void on_recv_error(const boost::system::error_code& ec)
......@@ -219,7 +213,7 @@ private:
{
assert(bytes_transferred == ST_THIS last_send_msg.size());
ST_THIS stat.send_time_sum += st_socket<Socket, Packer, Unpacker, in_msg_type, out_msg_type>::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_time_sum += super::statistic::local_time() - ST_THIS last_send_msg.begin_time;
ST_THIS stat.send_byte_sum += bytes_transferred;
++ST_THIS stat.send_msg_sum;
#ifdef ST_ASIO_WANT_MSG_SEND_NOTIFY
......@@ -252,11 +246,7 @@ protected:
boost::shared_mutex close_mutex;
};
typedef st_udp_socket_base<> st_udp_socket;
} //namespace st_udp
} //namespace st_asio_wrapper
using namespace st_asio_wrapper::st_udp; //compatible with old version which doesn't have st_udp namespace.
} //namespace
#endif /* ST_ASIO_WRAPPER_UDP_SOCKET_H_ */
......@@ -12,8 +12,9 @@
#define ST_ASIO_MSG_BUFFER_SIZE 65536
//configuration
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#ifdef _MSC_VER
#define atoll _atoi64
......@@ -104,7 +105,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: pingpong_client [service thread number=1] [<port=%d> [<ip=%s> [link num=16]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
printf("usage: pingpong_client [<service thread number=1> [<port=%d> [<ip=%s> [link num=16]]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
else
......
......@@ -9,8 +9,9 @@
#define ST_ASIO_MSG_BUFFER_SIZE 65536
//configuration
#include "../include/st_asio_wrapper_server.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#ifdef _MSC_VER
#define atoll _atoi64
......@@ -47,7 +48,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: pingpong_server [service thread number=1] [<port=%d> [ip=0.0.0.0]]\n", ST_ASIO_SERVER_PORT);
printf("usage: pingpong_server [<service thread number=1> [<port=%d> [ip=0.0.0.0]]]\n", ST_ASIO_SERVER_PORT);
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
else
......
......@@ -28,8 +28,9 @@
#define ST_ASIO_DEFAULT_UNPACKER prefix_suffix_unpacker
#endif
#include "../include/st_asio_wrapper_tcp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#ifdef _MSC_VER
#define atoll _atoi64
......@@ -206,7 +207,7 @@ public:
int main(int argc, const char* argv[])
{
printf("usage: test_client [service thread number=1] [<port=%d> [<ip=%s> [link num=16]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
printf("usage: test_client [<service thread number=1> [<port=%d> [<ip=%s> [link num=16]]]]\n", ST_ASIO_SERVER_PORT, ST_ASIO_SERVER_IP);
if (argc >= 2 && (0 == strcmp(argv[1], "--help") || 0 == strcmp(argv[1], "-h")))
return 0;
else
......
......@@ -6,8 +6,9 @@
//#define ST_ASIO_DEFAULT_UDP_UNPACKER replaceable_udp_unpacker
//configuration
#include "../include/st_asio_wrapper_udp_client.h"
#include "../include/ext/st_asio_wrapper_ext.h"
using namespace st_asio_wrapper;
using namespace st_asio_wrapper::ext;
#define QUIT_COMMAND "quit"
#define RESTART_COMMAND "restart"
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册