CppServer  1.0.4.0
C++ Server Library
udp_client.cpp
Go to the documentation of this file.
1 
10 
11 namespace CppServer {
12 namespace Asio {
13 
14 UDPClient::UDPClient(const std::shared_ptr<Service>& service, const std::string& address, int port)
15  : _id(CppCommon::UUID::Sequential()),
16  _service(service),
17  _io_service(_service->GetAsioService()),
18  _strand(*_io_service),
19  _strand_required(_service->IsStrandRequired()),
20  _address(address),
21  _port(port),
22  _socket(*_io_service),
23  _resolving(false),
24  _connected(false),
25  _bytes_sending(0),
26  _bytes_sent(0),
27  _bytes_received(0),
28  _datagrams_sent(0),
29  _datagrams_received(0),
30  _receiving(false),
31  _sending(false),
32  _option_reuse_address(false),
33  _option_reuse_port(false),
34  _option_multicast(false)
35 {
36  assert((service != nullptr) && "Asio service is invalid!");
37  if (service == nullptr)
38  throw CppCommon::ArgumentException("Asio service is invalid!");
39 }
40 
41 UDPClient::UDPClient(const std::shared_ptr<Service>& service, const std::string& address, const std::string& scheme)
42  : _id(CppCommon::UUID::Sequential()),
43  _service(service),
44  _io_service(_service->GetAsioService()),
45  _strand(*_io_service),
46  _strand_required(_service->IsStrandRequired()),
47  _address(address),
48  _scheme(scheme),
49  _port(0),
50  _socket(*_io_service),
51  _resolving(false),
52  _connected(false),
53  _bytes_sending(0),
54  _bytes_sent(0),
55  _bytes_received(0),
56  _datagrams_sent(0),
57  _datagrams_received(0),
58  _receiving(false),
59  _sending(false),
60  _option_reuse_address(false),
61  _option_reuse_port(false),
62  _option_multicast(false)
63 {
64  assert((service != nullptr) && "Asio service is invalid!");
65  if (service == nullptr)
66  throw CppCommon::ArgumentException("Asio service is invalid!");
67 }
68 
69 UDPClient::UDPClient(const std::shared_ptr<Service>& service, const asio::ip::udp::endpoint& endpoint)
70  : _id(CppCommon::UUID::Sequential()),
71  _service(service),
72  _io_service(_service->GetAsioService()),
73  _strand(*_io_service),
74  _strand_required(_service->IsStrandRequired()),
75  _address(endpoint.address().to_string()),
76  _port(endpoint.port()),
77  _endpoint(endpoint),
78  _socket(*_io_service),
79  _resolving(false),
80  _connected(false),
81  _bytes_sending(0),
82  _bytes_sent(0),
83  _bytes_received(0),
84  _datagrams_sent(0),
85  _datagrams_received(0),
86  _receiving(false),
87  _sending(false),
88  _option_reuse_address(false),
89  _option_reuse_port(false),
90  _option_multicast(false)
91 {
92  assert((service != nullptr) && "Asio service is invalid!");
93  if (service == nullptr)
94  throw CppCommon::ArgumentException("Asio service is invalid!");
95 }
96 
98 {
99  asio::socket_base::receive_buffer_size option;
100  _socket.get_option(option);
101  return option.value();
102 }
103 
105 {
106  asio::socket_base::send_buffer_size option;
107  _socket.get_option(option);
108  return option.value();
109 }
110 
112 {
113  asio::socket_base::receive_buffer_size option((int)size);
114  _socket.set_option(option);
115 }
116 
118 {
119  asio::socket_base::send_buffer_size option((int)size);
120  _socket.set_option(option);
121 }
122 
124 {
125  assert(!_address.empty() && "Server address must not be empty!");
126  if (_address.empty())
127  return false;
128  assert((_port > 0) && "Server port number must be valid!");
129  if (_port <= 0)
130  return false;
131 
132  if (IsConnected())
133  return false;
134 
135  // Create the server endpoint
136  _endpoint = asio::ip::udp::endpoint(asio::ip::make_address(_address), (unsigned short)_port);
137 
138  // Open a client socket
139  _socket.open(_endpoint.protocol());
140  if (option_reuse_address())
141  _socket.set_option(asio::ip::udp::socket::reuse_address(true));
142 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
143  if (option_reuse_port())
144  {
145  typedef asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT> reuse_port;
146  _socket.set_option(reuse_port(true));
147  }
148 #endif
149  if (option_multicast())
150  _socket.bind(_endpoint);
151  else
152  _socket.bind(asio::ip::udp::endpoint(_endpoint.protocol(), 0));
153 
154  // Prepare receive buffer
155  _receive_buffer.resize(option_receive_buffer_size());
156 
157  // Reset statistic
158  _bytes_sending = 0;
159  _bytes_sent = 0;
160  _bytes_received = 0;
161  _datagrams_sent = 0;
162  _datagrams_received = 0;
163 
164  // Update the connected flag
165  _connected = true;
166 
167  // Call the client connected handler
168  onConnected();
169 
170  return true;
171 }
172 
173 bool UDPClient::Connect(const std::shared_ptr<UDPResolver>& resolver)
174 {
175  assert((resolver != nullptr) && "UDP resolver is invalid!");
176  if (resolver == nullptr)
177  return false;
178  assert(!_address.empty() && "Server address must not be empty!");
179  if (_address.empty())
180  return false;
181  assert((_port > 0) && "Server port number must be valid!");
182  if (_port <= 0)
183  return false;
184 
185  if (IsConnected())
186  return false;
187 
188  std::error_code ec;
189 
190  // Resolve the server endpoint
191  asio::ip::udp::resolver::query query(_address, (_scheme.empty() ? std::to_string(_port) : _scheme));
192  auto endpoints = resolver->resolver().resolve(query, ec);
193 
194  // Check for resolve errors
195  if (ec)
196  {
197  SendError(ec);
198 
199  // Call the client disconnected handler
200  onDisconnected();
201 
202  return false;
203  }
204 
205  _endpoint = *endpoints;
206 
207  // Open a client socket
208  _socket.open(_endpoint.protocol());
209  if (option_reuse_address())
210  _socket.set_option(asio::ip::udp::socket::reuse_address(true));
211 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
212  if (option_reuse_port())
213  {
214  typedef asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT> reuse_port;
215  _socket.set_option(reuse_port(true));
216  }
217 #endif
218  if (option_multicast())
219  _socket.bind(_endpoint);
220  else
221  _socket.bind(asio::ip::udp::endpoint(_endpoint.protocol(), 0));
222 
223  // Prepare receive buffer
224  _receive_buffer.resize(option_receive_buffer_size());
225 
226  // Reset statistic
227  _bytes_sending = 0;
228  _bytes_sent = 0;
229  _bytes_received = 0;
230  _datagrams_sent = 0;
231  _datagrams_received = 0;
232 
233  // Update the connected flag
234  _connected = true;
235 
236  // Call the client connected handler
237  onConnected();
238 
239  return true;
240 }
241 
242 bool UDPClient::DisconnectInternal()
243 {
244  if (!IsConnected())
245  return false;
246 
247  // Close the client socket
248  _socket.close();
249 
250  // Update the connected flag
251  _resolving = false;
252  _connected = false;
253 
254  // Update sending/receiving flags
255  _receiving = false;
256  _sending = false;
257 
258  // Clear send/receive buffers
259  ClearBuffers();
260 
261  // Call the client disconnected handler
262  onDisconnected();
263 
264  return true;
265 }
266 
268 {
269  if (!Disconnect())
270  return false;
271 
272  return Connect();
273 }
274 
276 {
277  if (IsConnected())
278  return false;
279 
280  // Post the connect handler
281  auto self(this->shared_from_this());
282  auto connect_handler = [this, self]() { Connect(); };
283  if (_strand_required)
284  _strand.post(connect_handler);
285  else
286  _io_service->post(connect_handler);
287 
288  return true;
289 }
290 
291 bool UDPClient::ConnectAsync(const std::shared_ptr<UDPResolver>& resolver)
292 {
293  assert((resolver != nullptr) && "UDP resolver is invalid!");
294  if (resolver == nullptr)
295  return false;
296 
297  if (IsConnected() || _resolving)
298  return false;
299 
300  // Post the connect handler
301  auto self(this->shared_from_this());
302  auto connect_handler = [this, self, resolver]()
303  {
304  if (IsConnected() || _resolving)
305  return;
306 
307  // Async DNS resolve with the resolve handler
308  _resolving = true;
309  auto async_resolve_handler = [this, self](std::error_code ec, asio::ip::udp::resolver::results_type endpoints)
310  {
311  _resolving = false;
312 
313  if (IsConnected() || _resolving)
314  return;
315 
316  if (!ec)
317  {
318  // Resolve the server endpoint
319  _endpoint = *endpoints;
320 
321  // Open a client socket
322  _socket.open(_endpoint.protocol());
323  if (option_reuse_address())
324  _socket.set_option(asio::ip::udp::socket::reuse_address(true));
325 #if (defined(unix) || defined(__unix) || defined(__unix__) || defined(__APPLE__)) && !defined(__CYGWIN__)
326  if (option_reuse_port())
327  {
328  typedef asio::detail::socket_option::boolean<SOL_SOCKET, SO_REUSEPORT> reuse_port;
329  _socket.set_option(reuse_port(true));
330  }
331 #endif
332  if (option_multicast())
333  _socket.bind(_endpoint);
334  else
335  _socket.bind(asio::ip::udp::endpoint(_endpoint.protocol(), 0));
336 
337  // Prepare receive buffer
338  _receive_buffer.resize(option_receive_buffer_size());
339 
340  // Reset statistic
341  _bytes_sending = 0;
342  _bytes_sent = 0;
343  _bytes_received = 0;
344  _datagrams_sent = 0;
345  _datagrams_received = 0;
346 
347  // Update the connected flag
348  _connected = true;
349 
350  // Call the client connected handler
351  onConnected();
352  }
353  else
354  {
355  SendError(ec);
356 
357  // Call the client disconnected handler
358  onDisconnected();
359  }
360  };
361 
362  // Resolve the server endpoint
363  asio::ip::udp::resolver::query query(_address, (_scheme.empty() ? std::to_string(_port) : _scheme));
364  if (_strand_required)
365  resolver->resolver().async_resolve(query, bind_executor(_strand, async_resolve_handler));
366  else
367  resolver->resolver().async_resolve(query, async_resolve_handler);
368  };
369  if (_strand_required)
370  _strand.post(connect_handler);
371  else
372  _io_service->post(connect_handler);
373 
374  return true;
375 }
376 
377 bool UDPClient::DisconnectInternalAsync(bool dispatch)
378 {
379  if (!IsConnected())
380  return false;
381 
382  asio::error_code ec;
383 
384  // Cancel the client socket
385  _socket.cancel(ec);
386 
387  // Dispatch or post the disconnect handler
388  auto self(this->shared_from_this());
389  auto disconnect_handler = [this, self]() { DisconnectInternal(); };
390  if (_strand_required)
391  {
392  if (dispatch)
393  _strand.dispatch(disconnect_handler);
394  else
395  _strand.post(disconnect_handler);
396  }
397  else
398  {
399  if (dispatch)
400  _io_service->dispatch(disconnect_handler);
401  else
402  _io_service->post(disconnect_handler);
403  }
404 
405  return true;
406 }
407 
409 {
410  if (!DisconnectAsync())
411  return false;
412 
413  while (IsConnected())
414  CppCommon::Thread::Yield();
415 
416  return ConnectAsync();
417 }
418 
419 void UDPClient::JoinMulticastGroup(const std::string& address)
420 {
421  if (!IsConnected())
422  return;
423 
424  asio::ip::address muticast_address = asio::ip::make_address(address);
425 
426  asio::ip::multicast::join_group join(muticast_address);
427  _socket.set_option(join);
428 
429  // Call the client joined multicast group notification
431 }
432 
433 void UDPClient::LeaveMulticastGroup(const std::string& address)
434 {
435  if (!IsConnected())
436  return;
437 
438  asio::ip::address muticast_address = asio::ip::make_address(address);
439 
440  asio::ip::multicast::leave_group leave(muticast_address);
441  _socket.set_option(leave);
442 
443  // Call the client left multicast group notification
445 }
446 
447 void UDPClient::JoinMulticastGroupAsync(const std::string& address)
448 {
449  if (!IsConnected())
450  return;
451 
452  // Dispatch the join multicast group handler
453  auto self(this->shared_from_this());
454  auto join_multicast_group_handler = [this, self, address]() { JoinMulticastGroup(address); };
455  if (_strand_required)
456  _strand.dispatch(join_multicast_group_handler);
457  else
458  _io_service->dispatch(join_multicast_group_handler);
459 }
460 
461 void UDPClient::LeaveMulticastGroupAsync(const std::string& address)
462 {
463  if (!IsConnected())
464  return;
465 
466  // Dispatch the leave multicast group handler
467  auto self(this->shared_from_this());
468  auto leave_multicast_group_handler = [this, self, address]() { LeaveMulticastGroup(address); };
469  if (_strand_required)
470  _strand.dispatch(leave_multicast_group_handler);
471  else
472  _io_service->dispatch(leave_multicast_group_handler);
473 }
474 
475 size_t UDPClient::Send(const void* buffer, size_t size)
476 {
477  // Send the datagram to the server endpoint
478  return Send(_endpoint, buffer, size);
479 }
480 
481 size_t UDPClient::Send(const asio::ip::udp::endpoint& endpoint, const void* buffer, size_t size)
482 {
483  if (!IsConnected())
484  return 0;
485 
486  if (size == 0)
487  return 0;
488 
489  assert((buffer != nullptr) && "Pointer to the buffer should not be null!");
490  if (buffer == nullptr)
491  return 0;
492 
493  asio::error_code ec;
494 
495  // Sent datagram to the server
496  size_t sent = _socket.send_to(asio::const_buffer(buffer, size), endpoint, 0, ec);
497  if (sent > 0)
498  {
499  // Update statistic
500  ++_datagrams_sent;
501  _bytes_sent += sent;
502 
503  // Call the datagram sent handler
504  onSent(endpoint, sent);
505  }
506 
507  // Disconnect on error
508  if (ec)
509  {
510  SendError(ec);
511  Disconnect();
512  }
513 
514  return sent;
515 }
516 
517 size_t UDPClient::Send(const void* buffer, size_t size, const CppCommon::Timespan& timeout)
518 {
519  // Send the datagram to the server endpoint
520  return Send(_endpoint, buffer, size, timeout);
521 }
522 
523 size_t UDPClient::Send(const asio::ip::udp::endpoint& endpoint, const void* buffer, size_t size, const CppCommon::Timespan& timeout)
524 {
525  if (!IsConnected())
526  return 0;
527 
528  if (size == 0)
529  return 0;
530 
531  assert((buffer != nullptr) && "Pointer to the buffer should not be null!");
532  if (buffer == nullptr)
533  return 0;
534 
535  int done = 0;
536  std::mutex mtx;
537  std::condition_variable cv;
538  asio::error_code error;
539  asio::system_timer timer(_socket.get_executor());
540 
541  // Prepare done handler
542  auto async_done_handler = [&](asio::error_code ec)
543  {
544  std::unique_lock<std::mutex> lck(mtx);
545  if (done++ == 0)
546  {
547  error = ec;
548  _socket.cancel();
549  timer.cancel();
550  }
551  cv.notify_one();
552  };
553 
554  // Async wait for timeout
555  timer.expires_from_now(timeout.chrono());
556  timer.async_wait([&](const asio::error_code& ec) { async_done_handler(ec ? ec : asio::error::timed_out); });
557 
558  // Async send datagram to the server
559  size_t sent = 0;
560  _socket.async_send_to(asio::buffer(buffer, size), endpoint, [&](std::error_code ec, size_t write) { async_done_handler(ec); sent = write; });
561 
562  // Wait for complete or timeout
563  std::unique_lock<std::mutex> lck(mtx);
564  cv.wait(lck, [&]() { return done == 2; });
565 
566  // Send datagram to the server
567  if (sent > 0)
568  {
569  // Update statistic
570  ++_datagrams_sent;
571  _bytes_sent += sent;
572 
573  // Call the datagram sent handler
574  onSent(endpoint, sent);
575  }
576 
577  // Disconnect on error
578  if (error && (error != asio::error::timed_out))
579  {
580  SendError(error);
581  Disconnect();
582  }
583 
584  return sent;
585 }
586 
587 bool UDPClient::SendAsync(const void* buffer, size_t size)
588 {
589  // Send the datagram to the server endpoint
590  return SendAsync(_endpoint, buffer, size);
591 }
592 
593 bool UDPClient::SendAsync(const asio::ip::udp::endpoint& endpoint, const void* buffer, size_t size)
594 {
595  if (_sending)
596  return false;
597 
598  if (!IsConnected())
599  return false;
600 
601  if (size == 0)
602  return true;
603 
604  assert((buffer != nullptr) && "Pointer to the buffer should not be null!");
605  if (buffer == nullptr)
606  return false;
607 
608  // Check the send buffer limit
609  if ((size > _send_buffer_limit) && (_send_buffer_limit > 0))
610  {
611  SendError(asio::error::no_buffer_space);
612  return false;
613  }
614 
615  // Fill the main send buffer
616  const uint8_t* bytes = (const uint8_t*)buffer;
617  _send_buffer.assign(bytes, bytes + size);
618 
619  // Update statistic
620  _bytes_sending = _send_buffer.size();
621 
622  // Update send endpoint
623  _send_endpoint = endpoint;
624 
625  // Async send-to with the send-to handler
626  _sending = true;
627  auto self(this->shared_from_this());
628  auto async_send_to_handler = make_alloc_handler(_send_storage, [this, self](std::error_code ec, size_t sent)
629  {
630  _sending = false;
631 
632  if (!IsConnected())
633  return;
634 
635  // Disconnect on error
636  if (ec)
637  {
638  SendError(ec);
639  DisconnectInternalAsync(true);
640  return;
641  }
642 
643  // Send some data to the server
644  if (sent > 0)
645  {
646  // Update statistic
647  _bytes_sending = 0;
648  _bytes_sent += sent;
649 
650  // Clear the send buffer
651  _send_buffer.clear();
652 
653  // Call the buffer sent handler
654  onSent(_send_endpoint, sent);
655  }
656  });
657  if (_strand_required)
658  _socket.async_send_to(asio::buffer(_send_buffer.data(), _send_buffer.size()), _send_endpoint, bind_executor(_strand, async_send_to_handler));
659  else
660  _socket.async_send_to(asio::buffer(_send_buffer.data(), _send_buffer.size()), _send_endpoint, async_send_to_handler);
661 
662  return true;
663 }
664 
665 size_t UDPClient::Receive(asio::ip::udp::endpoint& endpoint, void* buffer, size_t size)
666 {
667  if (!IsConnected())
668  return 0;
669 
670  if (size == 0)
671  return 0;
672 
673  assert((buffer != nullptr) && "Pointer to the buffer should not be null!");
674  if (buffer == nullptr)
675  return 0;
676 
677  asio::error_code ec;
678 
679  // Receive datagram from the server
680  size_t received = _socket.receive_from(asio::buffer(buffer, size), endpoint, 0, ec);
681 
682  // Update statistic
683  ++_datagrams_received;
684  _bytes_received += received;
685 
686  // Call the datagram received handler
687  onReceived(endpoint, buffer, received);
688 
689  // Disconnect on error
690  if (ec)
691  {
692  SendError(ec);
693  Disconnect();
694  }
695 
696  return received;
697 }
698 
699 std::string UDPClient::Receive(asio::ip::udp::endpoint& endpoint, size_t size)
700 {
701  std::string text(size, 0);
702  text.resize(Receive(endpoint, text.data(), text.size()));
703  return text;
704 }
705 
706 size_t UDPClient::Receive(asio::ip::udp::endpoint& endpoint, void* buffer, size_t size, const CppCommon::Timespan& timeout)
707 {
708  if (!IsConnected())
709  return 0;
710 
711  if (size == 0)
712  return 0;
713 
714  assert((buffer != nullptr) && "Pointer to the buffer should not be null!");
715  if (buffer == nullptr)
716  return 0;
717 
718  int done = 0;
719  std::mutex mtx;
720  std::condition_variable cv;
721  asio::error_code error;
722  asio::system_timer timer(_socket.get_executor());
723 
724  // Prepare done handler
725  auto async_done_handler = [&](asio::error_code ec)
726  {
727  std::unique_lock<std::mutex> lck(mtx);
728  if (done++ == 0)
729  {
730  error = ec;
731  _socket.cancel();
732  timer.cancel();
733  }
734  cv.notify_one();
735  };
736 
737  // Async wait for timeout
738  timer.expires_from_now(timeout.chrono());
739  timer.async_wait([&](const asio::error_code& ec) { async_done_handler(ec ? ec : asio::error::timed_out); });
740 
741  // Async receive datagram from the server
742  size_t received = 0;
743  _socket.async_receive_from(asio::buffer(buffer, size), endpoint, [&](std::error_code ec, size_t read) { async_done_handler(ec); received = read; });
744 
745  // Wait for complete or timeout
746  std::unique_lock<std::mutex> lck(mtx);
747  cv.wait(lck, [&]() { return done == 2; });
748 
749  // Update statistic
750  ++_datagrams_received;
751  _bytes_received += received;
752 
753  // Call the datagram received handler
754  onReceived(endpoint, buffer, received);
755 
756  // Disconnect on error
757  if (error && (error != asio::error::timed_out))
758  {
759  SendError(error);
760  Disconnect();
761  }
762 
763  return received;
764 }
765 
766 std::string UDPClient::Receive(asio::ip::udp::endpoint& endpoint, size_t size, const CppCommon::Timespan& timeout)
767 {
768  std::string text(size, 0);
769  text.resize(Receive(endpoint, text.data(), text.size(), timeout));
770  return text;
771 }
772 
774 {
775  // Try to receive datagrams from the server
776  TryReceive();
777 }
778 
779 void UDPClient::TryReceive()
780 {
781  if (_receiving)
782  return;
783 
784  if (!IsConnected())
785  return;
786 
787  // Async receive with the receive handler
788  _receiving = true;
789  auto self(this->shared_from_this());
790  auto async_receive_handler = make_alloc_handler(_receive_storage, [this, self](std::error_code ec, size_t size)
791  {
792  _receiving = false;
793 
794  if (!IsConnected())
795  return;
796 
797  // Disconnect on error
798  if (ec)
799  {
800  SendError(ec);
801  DisconnectInternalAsync(true);
802  return;
803  }
804 
805  // Update statistic
806  ++_datagrams_received;
807  _bytes_received += size;
808 
809  // Call the datagram received handler
810  onReceived(_receive_endpoint, _receive_buffer.data(), size);
811 
812  // If the receive buffer is full increase its size
813  if (_receive_buffer.size() == size)
814  {
815  // Check the receive buffer limit
816  if (((2 * size) > _receive_buffer_limit) && (_receive_buffer_limit > 0))
817  {
818  SendError(asio::error::no_buffer_space);
819  DisconnectInternalAsync(true);
820  return;
821  }
822 
823  _receive_buffer.resize(2 * size);
824  }
825  });
826  if (_strand_required)
827  _socket.async_receive_from(asio::buffer(_receive_buffer.data(), _receive_buffer.size()), _receive_endpoint, bind_executor(_strand, async_receive_handler));
828  else
829  _socket.async_receive_from(asio::buffer(_receive_buffer.data(), _receive_buffer.size()), _receive_endpoint, async_receive_handler);
830 }
831 
832 void UDPClient::ClearBuffers()
833 {
834  // Clear send buffers
835  _send_buffer.clear();
836 
837  // Update statistic
838  _bytes_sending = 0;
839 }
840 
841 void UDPClient::SendError(std::error_code ec)
842 {
843  // Skip Asio disconnect errors
844  if ((ec == asio::error::connection_aborted) ||
845  (ec == asio::error::connection_refused) ||
846  (ec == asio::error::connection_reset) ||
847  (ec == asio::error::eof) ||
848  (ec == asio::error::operation_aborted))
849  return;
850 
851  onError(ec.value(), ec.category().name(), ec.message());
852 }
853 
854 } // namespace Asio
855 } // namespace CppServer
bool option_reuse_address() const noexcept
Get the option: reuse address.
Definition: udp_client.h:92
virtual void LeaveMulticastGroup(const std::string &address)
Leave multicast group with a given address (synchronous)
Definition: udp_client.cpp:433
virtual void onConnected()
Handle client connected notification.
Definition: udp_client.h:355
void SetupReceiveBufferSize(size_t size)
Setup option: receive buffer size.
Definition: udp_client.cpp:111
virtual size_t Receive(asio::ip::udp::endpoint &endpoint, void *buffer, size_t size)
Receive datagram from the given endpoint (synchronous)
Definition: udp_client.cpp:665
bool option_multicast() const noexcept
Get the option: bind the socket to the multicast UDP server.
Definition: udp_client.h:96
virtual bool ReconnectAsync()
Reconnect the client (asynchronous)
Definition: udp_client.cpp:408
bool IsConnected() const noexcept
Is the client connected?
Definition: udp_client.h:107
UDPClient(const std::shared_ptr< Service > &service, const std::string &address, int port)
Initialize UDP client with a given Asio service, server address and port number.
Definition: udp_client.cpp:14
const std::string & address() const noexcept
Get the server address.
Definition: udp_client.h:74
bool option_reuse_port() const noexcept
Get the option: reuse port.
Definition: udp_client.h:94
virtual void onDisconnected()
Handle client disconnected notification.
Definition: udp_client.h:357
virtual void LeaveMulticastGroupAsync(const std::string &address)
Leave multicast group with a given address (asynchronous)
Definition: udp_client.cpp:461
virtual void onSent(const asio::ip::udp::endpoint &endpoint, size_t sent)
Handle datagram sent notification.
Definition: udp_client.h:390
virtual void JoinMulticastGroupAsync(const std::string &address)
Join multicast group with a given address (asynchronous)
Definition: udp_client.cpp:447
virtual void onError(int error, const std::string &category, const std::string &message)
Handle error notification.
Definition: udp_client.h:398
virtual void JoinMulticastGroup(const std::string &address)
Join multicast group with a given address (synchronous)
Definition: udp_client.cpp:419
virtual bool Reconnect()
Reconnect the client (synchronous)
Definition: udp_client.cpp:267
virtual void onJoinedMulticastGroup(const std::string &address)
Handle client joined multicast group notification.
Definition: udp_client.h:363
std::shared_ptr< Service > & service() noexcept
Get the Asio service.
Definition: udp_client.h:63
virtual void ReceiveAsync()
Receive datagram from the server (asynchronous)
Definition: udp_client.cpp:773
virtual bool Connect()
Connect the client (synchronous)
Definition: udp_client.cpp:123
size_t option_send_buffer_size() const
Get the option: send buffer size.
Definition: udp_client.cpp:104
virtual void onReceived(const asio::ip::udp::endpoint &endpoint, const void *buffer, size_t size)
Handle datagram received notification.
Definition: udp_client.h:379
virtual bool SendAsync(const void *buffer, size_t size)
Send datagram to the connected server (asynchronous)
Definition: udp_client.cpp:587
void SetupSendBufferSize(size_t size)
Setup option: send buffer size.
Definition: udp_client.cpp:117
virtual bool DisconnectAsync()
Disconnect the client (asynchronous)
Definition: udp_client.h:146
virtual void onLeftMulticastGroup(const std::string &address)
Handle client left multicast group notification.
Definition: udp_client.h:368
virtual size_t Send(const void *buffer, size_t size)
Send datagram to the connected server (synchronous)
Definition: udp_client.cpp:475
virtual bool Disconnect()
Disconnect the client (synchronous)
Definition: udp_client.h:124
size_t option_receive_buffer_size() const
Get the option: receive buffer size.
Definition: udp_client.cpp:97
asio::ip::udp::endpoint & endpoint() noexcept
Get the client endpoint.
Definition: udp_client.h:69
virtual bool ConnectAsync()
Connect the client (asynchronous)
Definition: udp_client.cpp:275
AllocateHandler< THandler > make_alloc_handler(HandlerStorage &storage, THandler handler)
Helper function to wrap a handler object to add custom allocation.
Definition: memory.inl:39
C++ Server project definitions.
Definition: asio.h:56
UDP client definition.