Line data Source code
1 : // Copyright (c) 2012-2021 Made to Order Software Corp. All Rights Reserved
2 : //
3 : // https://snapwebsites.org/project/eventdispatcher
4 : // contact@m2osw.com
5 : //
6 : // This program is free software; you can redistribute it and/or modify
7 : // it under the terms of the GNU General Public License as published by
8 : // the Free Software Foundation; either version 2 of the License, or
9 : // (at your option) any later version.
10 : //
11 : // This program is distributed in the hope that it will be useful,
12 : // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 : // GNU General Public License for more details.
15 : //
16 : // You should have received a copy of the GNU General Public License
17 : // along with this program; if not, write to the Free Software
18 : // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 :
20 : /** \file
21 : * \brief Event dispatch class.
22 : *
23 : * Class used to handle events.
24 : */
25 :
26 :
27 : // self
28 : //
29 : #include "eventdispatcher/udp_client.h"
30 :
31 :
32 : // last include
33 : //
34 : #include <snapdev/poison.h>
35 :
36 :
37 :
38 : namespace ed
39 : {
40 :
41 :
42 :
43 : /** \brief Initialize a UDP client object.
44 : *
45 : * This function initializes the UDP client object using the address and the
46 : * port as specified.
47 : *
48 : * The port is expected to be a host side port number (i.e. 59200).
49 : *
50 : * The \p addr parameter is a textual address. It may be an IPv4 or IPv6
51 : * address and it can represent a host name or an address defined with
52 : * just numbers. If the address cannot be resolved then an error occurs
53 : * and the constructor throws.
54 : *
55 : * \note
56 : * The socket is open in this process. If you fork() or exec() then the
57 : * socket will be closed by the operating system.
58 : *
59 : * \warning
60 : * We only make use of the first address found by getaddrinfo(). All
61 : * the other addresses are ignored.
62 : *
63 : * \exception udp_client_server_runtime_error
64 : * The server could not be initialized properly. Either the address cannot be
65 : * resolved, the port is incompatible or not available, or the socket could
66 : * not be created.
67 : *
68 : * \param[in] addr The address to convert to a numeric IP.
69 : * \param[in] port The port number.
70 : * \param[in] family The family used to search for 'addr'.
71 : */
72 0 : udp_client::udp_client(std::string const & addr, int port, int family)
73 0 : : udp_base(addr, port, family)
74 : {
75 0 : }
76 :
77 :
78 : /** \brief Clean up the UDP client object.
79 : *
80 : * This function frees the address information structure and close the socket
81 : * before returning.
82 : */
83 0 : udp_client::~udp_client()
84 : {
85 0 : }
86 :
87 :
88 : /** \brief Send a message through this UDP client.
89 : *
90 : * This function sends \p msg through the UDP client socket. The function
91 : * cannot be used to change the destination as it was defined when creating
92 : * the udp_client object.
93 : *
94 : * The size must be small enough for the message to fit. In most cases, we
95 : * use these in Snap! to send very small signals (i.e. 4 bytes commands.)
96 : * Any data we would want to share remains in the Cassandra database so
97 : * that way we can avoid losing it because of a UDP message.
98 : *
99 : * \note
100 : * The send may fail with EAGAIN, EWOULDBLOCK, or ENOBUFS which all mean
101 : * that the attempt can be tried again. The ENOBUFS means that a new buffer
102 : * could not be allocated, not that the UDP queue is full or that packets
103 : * are being lost because too many are being sent in a row. Also, you want
104 : * to control the size of your buffer with get_mss_size(). UDP buffers that
105 : * are larger will be broken up in multiple packets and that increases the
106 : * chance that the packet never arrives. Also over a certain size (probably
107 : * around 64K in IPv4) the ENOBUFS automatically happens. Note that IPv6
108 : * allows for much buffer packets. This is not automatically a good idea
109 : * unless the number of packets is quite small because when it fails, you
110 : * have to resend a very large packet...
111 : *
112 : * \note
113 : * To avoid drop of UDP messages, you need to time your calls to the send()
114 : * function taking in account the amount of data being sent and the network
115 : * speed. On the lo network, the throughput is very high and packets can be
116 : * really large (nearly 64Kb). On a local network, check the size with the
117 : * get_mss_size() function and (TBD how?) check the speed. You certainly
118 : * can use up to about 95% of the speed without much problems assuming that
119 : * the pipe is only used by these UDP packets. Too much and the dropping is
120 : * going to increase steadily.
121 : *
122 : * \param[in] msg The message to send.
123 : * \param[in] size The number of bytes representing this message.
124 : *
125 : * \return -1 if an error occurs, otherwise the number of bytes sent. errno
126 : * is set accordingly on error.
127 : */
128 0 : int udp_client::send(char const * msg, size_t size)
129 : {
130 0 : return static_cast<int>(sendto(f_socket.get(), msg, size, 0, f_addrinfo->ai_addr, f_addrinfo->ai_addrlen));
131 : }
132 :
133 :
134 :
135 6 : } // namespace ed
136 : // vim: ts=4 sw=4 et
|