CppServer  1.0.0.0
C++ Server Library
server.cpp
Go to the documentation of this file.
1 
10 
11 #include "errors/fatal.h"
12 #include "threads/thread.h"
13 
14 #include <cassert>
15 
16 namespace CppServer {
17 namespace Nanomsg {
18 
19 Server::Server(Domain domain, Protocol protocol, const std::string& address, bool threading)
20  : _address(address),
21  _socket(domain, protocol),
22  _connected(false),
23  _threading(threading),
24  _joining(false),
25  _receiving(false)
26 {
27  // Start the server thread
28  if (_threading)
29  _thread = CppCommon::Thread::Start([this]() { ServerLoop(); });
30 }
31 
33 {
34  if (IsStarted())
35  Stop();
36 
37  // Wait for server thread
38  if (_threading)
39  {
40  _joining = true;
41  if (_thread.joinable())
42  _thread.join();
43  }
44 }
45 
47 {
48  assert(!IsStarted() && "Nanomsg server is already started!");
49  if (IsStarted())
50  return false;
51 
52  try
53  {
54  if (_socket.Bind(_address))
55  {
56  _connected = true;
57 
58  // Call the server started handler
59  onStarted();
60 
61  return true;
62  }
63  else
64  return false;
65  }
66  catch (CppCommon::SystemException& ex)
67  {
68  onError(ex.system_error(), ex.string());
69  return false;
70  }
71 }
72 
74 {
75  assert(IsStarted() && "Nanomsg server is not started!");
76  if (!IsStarted())
77  return false;
78 
79  try
80  {
81  if (_socket.Disconnect())
82  {
83  _connected = false;
84 
85  // Call the server stopped handler
86  onStopped();
87 
88  return true;
89  }
90  else
91  return false;
92  }
93  catch (CppCommon::SystemException& ex)
94  {
95  onError(ex.system_error(), ex.string());
96  return false;
97  }
98 }
99 
101 {
102  if (!Stop())
103  return false;
104 
105  // Reopen Nanomsg socket
106  _socket.Reopen();
107 
108  return Start();
109 }
110 
111 void Server::ServerLoop()
112 {
113  // Call the initialize thread handler
115 
116  try
117  {
118  while (!_joining)
119  {
120  // Run Nanomsg receive loop
121  while (IsStarted())
122  {
123  _receiving = true;
124 
125  // Try to receive a new message from the client
126  Message message;
127  if (TryReceive(message) == 0)
128  {
129  // Call the idle handler
130  onIdle();
131  }
132 
133  _receiving = false;
134  }
135 
136  // Switch to another thread...
137  CppCommon::Thread::Yield();
138  }
139  }
140  catch (CppCommon::SystemException& ex)
141  {
142  onError(ex.system_error(), ex.string());
143  }
144  catch (std::exception& ex)
145  {
146  fatality(ex);
147  }
148  catch (...)
149  {
150  fatality("Nanomsg server thread terminated!");
151  }
152 
153  // Call the cleanup thread handler
154  onThreadCleanup();
155 }
156 
157 size_t Server::Send(const void* buffer, size_t size)
158 {
159  if (!IsStarted())
160  return 0;
161 
162  try
163  {
164  return _socket.Send(buffer, size);
165  }
166  catch (CppCommon::SystemException& ex)
167  {
168  onError(ex.system_error(), ex.string());
169  return 0;
170  }
171 }
172 
173 size_t Server::TrySend(const void* buffer, size_t size)
174 {
175  if (!IsStarted())
176  return 0;
177 
178  try
179  {
180  return _socket.TrySend(buffer, size);
181  }
182  catch (CppCommon::SystemException& ex)
183  {
184  onError(ex.system_error(), ex.string());
185  return 0;
186  }
187 }
188 
189 size_t Server::Receive(Message& message)
190 {
191  if (!IsStarted())
192  return 0;
193 
194  try
195  {
196  size_t result = _socket.Receive(message);
197  if (result > 0)
198  {
199  // Call the message received handler
200  onReceived(message);
201  }
202  return result;
203  }
204  catch (CppCommon::SystemException& ex)
205  {
206  onError(ex.system_error(), ex.string());
207  return 0;
208  }
209 }
210 
211 size_t Server::TryReceive(Message& message)
212 {
213  if (!IsStarted())
214  return 0;
215 
216  try
217  {
218  size_t result = _socket.TryReceive(message);
219  if (result > 0)
220  {
221  // Call the message received handler
222  onReceived(message);
223  }
224  return result;
225  }
226  catch (CppCommon::SystemException& ex)
227  {
228  onError(ex.system_error(), ex.string());
229  return 0;
230  }
231 }
232 
233 } // namespace Nanomsg
234 } // namespace CppServer
bool Reopen()
Reopen the socket.
Definition: socket.cpp:128
virtual void onStarted()
Handle server started notification.
Definition: server.h:136
size_t Send(const void *buffer, size_t size)
Send data to the client.
Definition: server.cpp:157
size_t TrySend(const void *buffer, size_t size)
Try to send data to the socket in non-blocking mode.
Definition: socket.cpp:271
Nanomsg message.
Definition: message.h:29
bool Start()
Start the server.
Definition: server.cpp:46
size_t TryReceive(Message &message)
Try to receive a message from the client in non-blocking mode.
Definition: server.cpp:211
C++ Server project definitions.
Definition: asio.h:24
bool Restart()
Restart the server.
Definition: server.cpp:100
bool Bind(const std::string &address)
Bind the socket to the local endpoint.
Definition: socket.cpp:168
bool Stop()
Stop the server.
Definition: server.cpp:73
virtual void onThreadCleanup()
Cleanup thread handler.
Definition: server.h:133
virtual void onIdle()
Handle server idle notification.
Definition: server.h:141
virtual void onThreadInitialize()
Initialize thread handler.
Definition: server.h:128
Nanomsg server definition.
Server(Domain domain, Protocol protocol, const std::string &address, bool threading=true)
Initialize server with a given domain, protocol and endpoint address.
Definition: server.cpp:19
virtual void onReceived(Message &message)
Handle message received notification.
Definition: server.h:147
bool IsStarted() const noexcept
Is the server started?
Definition: server.h:51
Protocol
Nanomsg protocol.
Definition: nanomsg.h:56
size_t Receive(Message &message)
Receive a message from the socket in non-blocking mode.
Definition: socket.cpp:297
size_t Send(const void *buffer, size_t size)
Send data to the socket.
Definition: socket.cpp:247
Domain
Nanomsg domain.
Definition: nanomsg.h:41
size_t Receive(Message &message)
Receive a message from the client.
Definition: server.cpp:189
virtual void onError(int error, const std::string &message)
Handle error notification.
Definition: server.h:154
size_t TrySend(const void *buffer, size_t size)
Try to send data to the client in non-blocking mode.
Definition: server.cpp:173
size_t TryReceive(Message &message)
Try to receive a message from the socket in non-blocking mode.
Definition: socket.cpp:323
bool Disconnect()
Disconnect the socket from the endpoint.
Definition: socket.cpp:226
virtual void onStopped()
Handle server stopped notification.
Definition: server.h:138