From 5ecc4dde3731724f28d4629f8a563f30bb260617 Mon Sep 17 00:00:00 2001 From: Tobias Frust Date: Wed, 29 Jun 2016 15:22:50 +0200 Subject: added udpClient, which will later send out the packages --- src/UDPClient/UDPClient.cpp | 12 ++++++++++++ src/UDPClient/UDPClient.h | 15 +++++++++++++++ 2 files changed, 27 insertions(+) create mode 100644 src/UDPClient/UDPClient.cpp create mode 100644 src/UDPClient/UDPClient.h (limited to 'src/UDPClient') diff --git a/src/UDPClient/UDPClient.cpp b/src/UDPClient/UDPClient.cpp new file mode 100644 index 0000000..640555f --- /dev/null +++ b/src/UDPClient/UDPClient.cpp @@ -0,0 +1,12 @@ +/* + * Copyright 2016 Tobias Frust + * + * UDPSender.cpp + * + * Created on: 29.06.2016 + * Author: Tobias Frust + */ + + + + diff --git a/src/UDPClient/UDPClient.h b/src/UDPClient/UDPClient.h new file mode 100644 index 0000000..a962fe9 --- /dev/null +++ b/src/UDPClient/UDPClient.h @@ -0,0 +1,15 @@ +/* + * Copyright 2016 Tobias Frust + * + * UDPSender.h + * + * Created on: 29.06.2016 + * Author: Tobias Frust + */ + +#ifndef UDPSENDER_H_ +#define UDPSENDER_H_ + + + +#endif /* UDPSENDER_H_ */ -- cgit v1.2.3 From 38b0d8ad024d11fa643934b0c56690b0e57c3e35 Mon Sep 17 00:00:00 2001 From: Tobias Frust Date: Wed, 29 Jun 2016 19:16:11 +0200 Subject: added UDP-Client and Server classes for data transfer via Ethernet --- src/UDPClient/UDPClient.cpp | 130 +++++++++++++++++++++++++++++++++++++++++++- src/UDPClient/UDPClient.h | 37 +++++++++++-- 2 files changed, 162 insertions(+), 5 deletions(-) (limited to 'src/UDPClient') diff --git a/src/UDPClient/UDPClient.cpp b/src/UDPClient/UDPClient.cpp index 640555f..75e81e1 100644 --- a/src/UDPClient/UDPClient.cpp +++ b/src/UDPClient/UDPClient.cpp @@ -1,5 +1,5 @@ /* - * Copyright 2016 Tobias Frust + * http://linux.m2osw.com/c-implementation-udp-clientserver * * UDPSender.cpp * @@ -7,6 +7,134 @@ * Author: Tobias Frust */ + // ========================= CLIENT ========================= + /** \brief Initialize a UDP client object. + * + * This function initializes the UDP client object using the address and the + * port as specified. + * + * The port is expected to be a host side port number (i.e. 59200). + * + * The \p addr parameter is a textual address. It may be an IPv4 or IPv6 + * address and it can represent a host name or an address defined with + * just numbers. If the address cannot be resolved then an error occurs + * and constructor throws. + * + * \note + * The socket is open in this process. If you fork() or exec() then the + * socket will be closed by the operating system. + * + * \warning + * We only make use of the first address found by getaddrinfo(). All + * the other addresses are ignored. + * + * \exception udp_client_server_runtime_error + * The server could not be initialized properly. Either the address cannot be + * resolved, the port is incompatible or not available, or the socket could + * not be created. + * + * \param[in] addr The address to convert to a numeric IP. + * \param[in] port The port number. + */ +#include "UDPClient.h" +#include +#include + +#ifndef SOCK_CLOEXEC +#define SOCK_CLOEXEC 0 +#endif + + UDPClient::UDPClient(const std::string& addr, int port) + : f_port(port) + , f_addr(addr){ + char decimal_port[16]; + snprintf(decimal_port, sizeof(decimal_port), "%d", f_port); + decimal_port[sizeof(decimal_port) / sizeof(decimal_port[0]) - 1] = '\0'; + struct addrinfo hints; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_DGRAM; + hints.ai_protocol = IPPROTO_UDP; + int r(getaddrinfo(addr.c_str(), decimal_port, &hints, &f_addrinfo)); + if(r != 0 || f_addrinfo == NULL) + { + throw udp_client_server_runtime_error(("invalid address or port: \"" + addr + ":" + decimal_port + "\"").c_str()); + } + f_socket = socket(f_addrinfo->ai_family, SOCK_DGRAM | SOCK_CLOEXEC, IPPROTO_UDP); + if(f_socket == -1) + { + freeaddrinfo(f_addrinfo); + throw udp_client_server_runtime_error(("could not create socket for: \"" + addr + ":" + decimal_port + "\"").c_str()); + } + } + + /** \brief Clean up the UDP client object. + * + * This function frees the address information structure and close the socket + * before returning. + */ + UDPClient::~UDPClient() + { + freeaddrinfo(f_addrinfo); + close(f_socket); + } + + /** \brief Retrieve a copy of the socket identifier. + * + * This function return the socket identifier as returned by the socket() + * function. This can be used to change some flags. + * + * \return The socket used by this UDP client. + */ + int UDPClient::get_socket() const { + return f_socket; + } + + /** \brief Retrieve the port used by this UDP client. + * + * This function returns the port used by this UDP client. The port is + * defined as an integer, host side. + * + * \return The port as expected in a host integer. + */ + int UDPClient::get_port() const { + return f_port; + } + + /** \brief Retrieve a copy of the address. + * + * This function returns a copy of the address as it was specified in the + * constructor. This does not return a canonalized version of the address. + * + * The address cannot be modified. If you need to send data on a different + * address, create a new UDP client. + * + * \return A string with a copy of the constructor input address. + */ + std::string UDPClient::get_addr() const { + return f_addr; + } + + /** \brief Send a message through this UDP client. + * + * This function sends \p msg through the UDP client socket. The function + * cannot be used to change the destination as it was defined when creating + * the udp_client object. + * + * The size must be small enough for the message to fit. In most cases we + * use these in Snap! to send very small signals (i.e. 4 bytes commands.) + * Any data we would want to share remains in the Cassandra database so + * that way we can avoid losing it because of a UDP message. + * + * \param[in] msg The message to send. + * \param[in] size The number of bytes representing this message. + * + * \return -1 if an error occurs, otherwise the number of bytes sent. errno + * is set accordingly on error. + */ + int UDPClient::send(const char *msg, size_t size){ + return sendto(f_socket, msg, size, 0, f_addrinfo->ai_addr, f_addrinfo->ai_addrlen); + } diff --git a/src/UDPClient/UDPClient.h b/src/UDPClient/UDPClient.h index a962fe9..f6cf0d6 100644 --- a/src/UDPClient/UDPClient.h +++ b/src/UDPClient/UDPClient.h @@ -1,5 +1,5 @@ /* - * Copyright 2016 Tobias Frust + * http://linux.m2osw.com/c-implementation-udp-clientserver * * UDPSender.h * @@ -7,9 +7,38 @@ * Author: Tobias Frust */ -#ifndef UDPSENDER_H_ -#define UDPSENDER_H_ +#ifndef UDPCLIENT_H_ +#define UDPCLIENT_H_ +#include +#include +#include +#include +#include +class udp_client_server_runtime_error : public std::runtime_error +{ +public: + udp_client_server_runtime_error(const char *w) : std::runtime_error(w) {} +}; -#endif /* UDPSENDER_H_ */ + +class UDPClient { +public: + UDPClient(const std::string& addr, int port); + ~UDPClient(); + + int get_socket() const; + int get_port() const; + std::string get_addr() const; + + int send(const char *msg, size_t size); + +private: + int f_socket; + int f_port; + std::string f_addr; + struct addrinfo * f_addrinfo; +}; + +#endif /* UDPCLIENT_H_ */ -- cgit v1.2.3 From dbf28e725f062744222559257abe64d8a39a9d50 Mon Sep 17 00:00:00 2001 From: Tobias Frust Date: Thu, 30 Jun 2016 10:27:20 +0200 Subject: bug fixes --- src/UDPClient/UDPClient.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/UDPClient') diff --git a/src/UDPClient/UDPClient.cpp b/src/UDPClient/UDPClient.cpp index 75e81e1..844b7f9 100644 --- a/src/UDPClient/UDPClient.cpp +++ b/src/UDPClient/UDPClient.cpp @@ -135,6 +135,6 @@ * \return -1 if an error occurs, otherwise the number of bytes sent. errno * is set accordingly on error. */ - int UDPClient::send(const char *msg, size_t size){ + int UDPClient::send(const char *msg, std::size_t size){ return sendto(f_socket, msg, size, 0, f_addrinfo->ai_addr, f_addrinfo->ai_addrlen); } -- cgit v1.2.3 From 0c33319451deec9b5461b57856423bc619817245 Mon Sep 17 00:00:00 2001 From: Tobias Frust Date: Thu, 30 Jun 2016 15:22:07 +0200 Subject: added classes for detector; Sending out in n different streams with n different ports --- src/UDPClient/UDPClient.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/UDPClient') diff --git a/src/UDPClient/UDPClient.cpp b/src/UDPClient/UDPClient.cpp index 844b7f9..1d427ba 100644 --- a/src/UDPClient/UDPClient.cpp +++ b/src/UDPClient/UDPClient.cpp @@ -50,6 +50,7 @@ UDPClient::UDPClient(const std::string& addr, int port) : f_port(port) , f_addr(addr){ + printf("Creating client %d\n", f_port); char decimal_port[16]; snprintf(decimal_port, sizeof(decimal_port), "%d", f_port); decimal_port[sizeof(decimal_port) / sizeof(decimal_port[0]) - 1] = '\0'; @@ -69,6 +70,7 @@ freeaddrinfo(f_addrinfo); throw udp_client_server_runtime_error(("could not create socket for: \"" + addr + ":" + decimal_port + "\"").c_str()); } + printf("Created client %d\n", f_port); } /** \brief Clean up the UDP client object. -- cgit v1.2.3