15 : _id(CppCommon::UUID::Sequential()),
17 _io_service(_service->GetAsioService()),
18 _strand(*_io_service),
19 _strand_required(_service->IsStrandRequired()),
21 _acceptor(*_io_service),
26 _option_keep_alive(false),
27 _option_no_delay(false),
28 _option_reuse_address(false),
29 _option_reuse_port(false)
31 assert((
service !=
nullptr) &&
"Asio service is invalid!");
33 throw CppCommon::ArgumentException(
"Asio service is invalid!");
39 _endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v4(), (
unsigned short)
port);
42 _endpoint = asio::ip::tcp::endpoint(asio::ip::tcp::v6(), (
unsigned short)
port);
48 : _id(CppCommon::UUID::Sequential()),
50 _io_service(_service->GetAsioService()),
51 _strand(*_io_service),
52 _strand_required(_service->IsStrandRequired()),
55 _acceptor(*_io_service),
60 _option_keep_alive(false),
61 _option_no_delay(false),
62 _option_reuse_address(false),
63 _option_reuse_port(false)
65 assert((
service !=
nullptr) &&
"Asio service is invalid!");
67 throw CppCommon::ArgumentException(
"Asio service is invalid!");
70 _endpoint = asio::ip::tcp::endpoint(asio::ip::make_address(
address), (
unsigned short)
port);
74 : _id(CppCommon::UUID::Sequential()),
76 _io_service(_service->GetAsioService()),
77 _strand(*_io_service),
78 _strand_required(_service->IsStrandRequired()),
79 _address(endpoint.address().to_string()),
80 _port(endpoint.port()),
82 _acceptor(*_io_service),
87 _option_keep_alive(false),
88 _option_no_delay(false),
89 _option_reuse_address(false),
90 _option_reuse_port(false)
92 assert((
service !=
nullptr) &&
"Asio service is invalid!");
94 throw CppCommon::ArgumentException(
"Asio service is invalid!");
99 assert(!
IsStarted() &&
"TCP server is already started!");
104 auto self(this->shared_from_this());
105 auto start_handler = [
this,
self]()
111 _acceptor = asio::ip::tcp::acceptor(*_io_service);
112 _acceptor.open(_endpoint.protocol());
114 _acceptor.set_option(asio::ip::tcp::acceptor::reuse_address(
true));
115 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
118 typedef asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT> reuse_port;
119 _acceptor.set_option(reuse_port(
true));
122 _acceptor.bind(_endpoint);
139 if (_strand_required)
140 _strand.post(start_handler);
142 _io_service->post(start_handler);
149 assert(
IsStarted() &&
"TCP server is not started!");
154 auto self(this->shared_from_this());
155 auto stop_handler = [
this,
self]()
164 _session->ResetServer();
178 if (_strand_required)
179 _strand.post(stop_handler);
181 _io_service->post(stop_handler);
192 CppCommon::Thread::Yield();
197 void TCPServer::Accept()
203 auto self(this->shared_from_this());
212 auto async_accept_handler =
make_alloc_handler(_acceptor_storage, [
this,
self](std::error_code ec)
227 if (_strand_required)
228 _acceptor.async_accept(_session->socket(), bind_executor(_strand, async_accept_handler));
230 _acceptor.async_accept(_session->socket(), async_accept_handler);
232 if (_strand_required)
233 _strand.dispatch(accept_handler);
235 _io_service->dispatch(accept_handler);
246 assert((buffer !=
nullptr) &&
"Pointer to the buffer should not be null!");
247 if (buffer ==
nullptr)
254 session.second->SendAsync(buffer, size);
265 auto self(this->shared_from_this());
266 auto disconnect_all_handler = [
this,
self]()
275 session.second->Disconnect();
277 if (_strand_required)
278 _strand.dispatch(disconnect_all_handler);
280 _io_service->dispatch(disconnect_all_handler);
291 return (it !=
_sessions.end()) ? it->second :
nullptr;
294 void TCPServer::RegisterSession()
299 _sessions.emplace(_session->id(), _session);
302 void TCPServer::UnregisterSession(
const CppCommon::UUID&
id)
315 void TCPServer::ClearBuffers()
321 void TCPServer::SendError(std::error_code ec)
324 if ((ec == asio::error::connection_aborted) ||
325 (ec == asio::error::connection_refused) ||
326 (ec == asio::error::connection_reset) ||
327 (ec == asio::error::eof) ||
328 (ec == asio::error::operation_aborted))
332 if (ec.value() == 995)
335 onError(ec.value(), ec.category().name(), ec.message());
virtual bool DisconnectAll()
Disconnect all connected sessions.
virtual bool Multicast(const void *buffer, size_t size)
Multicast data to all connected sessions.
virtual bool Start()
Start the server.
std::map< CppCommon::UUID, std::shared_ptr< TCPSession > > _sessions
std::shared_mutex _sessions_lock
std::shared_ptr< TCPSession > FindSession(const CppCommon::UUID &id)
Find a session with a given Id.
const std::string & address() const noexcept
Get the server address.
TCPServer(const std::shared_ptr< Service > &service, int port, InternetProtocol protocol=InternetProtocol::IPv4)
Initialize TCP server with a given Asio service and port number.
virtual bool Stop()
Stop the server.
bool option_reuse_port() const noexcept
Get the option: reuse port.
std::shared_ptr< Service > & service() noexcept
Get the Asio service.
virtual std::shared_ptr< TCPSession > CreateSession(const std::shared_ptr< TCPServer > &server)
Create TCP session factory method.
int port() const noexcept
Get the server port number.
virtual bool Restart()
Restart the server.
virtual void onStopped()
Handle server stopped notification.
virtual void onStarted()
Handle server started notification.
bool IsStarted() const noexcept
Is the server started?
virtual void onError(int error, const std::string &category, const std::string &message)
Handle error notification.
bool option_reuse_address() const noexcept
Get the option: reuse address.
AllocateHandler< THandler > make_alloc_handler(HandlerStorage &storage, THandler handler)
Helper function to wrap a handler object to add custom allocation.
InternetProtocol
Internet protocol.
@ IPv4
Internet Protocol version 4.
@ IPv6
Internet Protocol version 6.
C++ Server project definitions.