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