CppServer 1.0.5.0
C++ Server Library
Loading...
Searching...
No Matches
udp_client.cpp
Go to the documentation of this file.
1
10
11namespace CppServer {
12namespace Asio {
13
14UDPClient::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
41UDPClient::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
69UDPClient::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());
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
173bool 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
201
202 return false;
203 }
204
205 _endpoint = *endpoints;
206
207 // Open a client socket
208 _socket.open(_endpoint.protocol());
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
242bool 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
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
291bool 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());
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
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
377bool 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
419void 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
433void 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
447void 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());
455 if (_strand_required)
456 _strand.dispatch(join_multicast_group_handler);
457 else
458 _io_service->dispatch(join_multicast_group_handler);
459}
460
461void 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());
469 if (_strand_required)
470 _strand.dispatch(leave_multicast_group_handler);
471 else
472 _io_service->dispatch(leave_multicast_group_handler);
473}
474
475size_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
481size_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
505 }
506
507 // Disconnect on error
508 if (ec)
509 {
510 SendError(ec);
511 Disconnect();
512 }
513
514 return sent;
515}
516
517size_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
523size_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
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
587bool 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
593bool 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
665size_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
688
689 // Disconnect on error
690 if (ec)
691 {
692 SendError(ec);
693 Disconnect();
694 }
695
696 return received;
697}
698
699std::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
706size_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
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
766std::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
779void 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
832void UDPClient::ClearBuffers()
833{
834 // Clear send buffers
835 _send_buffer.clear();
836
837 // Update statistic
838 _bytes_sending = 0;
839}
840
841void 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
Asio allocate handler wrapper.
Definition memory.h:133
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)
virtual void onConnected()
Handle client connected notification.
Definition udp_client.h:355
asio::ip::udp::endpoint & endpoint() noexcept
Get the client endpoint.
Definition udp_client.h:69
void SetupReceiveBufferSize(size_t size)
Setup option: receive buffer size.
virtual size_t Receive(asio::ip::udp::endpoint &endpoint, void *buffer, size_t size)
Receive datagram from the given endpoint (synchronous)
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)
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.
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)
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)
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)
virtual bool Reconnect()
Reconnect the client (synchronous)
virtual void onJoinedMulticastGroup(const std::string &address)
Handle client joined multicast group notification.
Definition udp_client.h:363
virtual void ReceiveAsync()
Receive datagram from the server (asynchronous)
virtual bool Connect()
Connect the client (synchronous)
size_t option_send_buffer_size() const
Get the option: send buffer size.
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)
void SetupSendBufferSize(size_t size)
Setup option: send buffer size.
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)
std::shared_ptr< Service > & service() noexcept
Get the Asio service.
Definition udp_client.h:63
const std::string & address() const noexcept
Get the server address.
Definition udp_client.h:74
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.
virtual bool ConnectAsync()
Connect the client (asynchronous)
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.