From f2a7f28335c7dce9b1ea54b2f371d34c7fbf0d21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sergi=20Hern=C3=A0ndez=20Juan?= <shernand@iri.upc.edu> Date: Wed, 11 Jul 2012 16:51:00 +0000 Subject: [PATCH] Added a new class for UDP sockets. Added a send and receive examples for the UDP sockets. --- src/CMakeLists.txt | 4 +- src/examples/CMakeLists.txt | 12 ++++ src/examples/test_simple_client.cpp | 2 +- src/examples/test_simple_client_udp_rx.cpp | 32 +++++++++ src/examples/test_simple_client_udp_tx.cpp | 29 ++++++++ src/examples/test_simple_server.cpp | 4 +- src/sockets/socket.cpp | 29 ++++++-- src/sockets/socket.h | 14 +++- src/sockets/socketclient.cpp | 2 +- src/sockets/socketudp.cpp | 77 ++++++++++++++++++++++ src/sockets/socketudp.h | 57 ++++++++++++++++ 11 files changed, 249 insertions(+), 13 deletions(-) create mode 100755 src/examples/test_simple_client_udp_rx.cpp create mode 100755 src/examples/test_simple_client_udp_tx.cpp create mode 100755 src/sockets/socketudp.cpp create mode 100755 src/sockets/socketudp.h diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab89639..51fc516 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -33,9 +33,9 @@ ELSE(FTDI_INCLUDE_DIR AND FTDI_LIBRARY) ENDIF(FTDI_INCLUDE_DIR AND FTDI_LIBRARY) # edit the following line to add all the source code files of the library -SET(sources ./comm.cpp ./cqueue.cpp ./commexceptions.cpp ./serial/rs232.cpp ./serial/rs232exceptions.cpp ./sockets/socket.cpp ./sockets/socketclient.cpp ./sockets/socketserver.cpp ./sockets/socketexceptions.cpp ./can/can.cpp) +SET(sources ./comm.cpp ./cqueue.cpp ./commexceptions.cpp ./serial/rs232.cpp ./serial/rs232exceptions.cpp ./sockets/socket.cpp ./sockets/socketclient.cpp ./sockets/socketserver.cpp ./sockets/socketudp.cpp ./sockets/socketexceptions.cpp ./can/can.cpp) # edit the following line to add all the header files of the library -SET(headers ./comm.h ./cqueue.h ./commexceptions.h ./serial/rs232.h ./serial/rs232exceptions.h ./sockets/socket.h ./sockets/socketclient.h ./sockets/socketserver.h ./sockets/socketexceptions.h ./can/can.h) +SET(headers ./comm.h ./cqueue.h ./commexceptions.h ./serial/rs232.h ./serial/rs232exceptions.h ./sockets/socket.h ./sockets/socketclient.h ./sockets/socketserver.h ./sockets/socketudp.h ./sockets/socketexceptions.h ./can/can.h) IF(BUILD_FTDI) SET(sources ${sources} ./usb_ftdi/ftdiserver.cpp ./usb_ftdi/ftdimodule.cpp ./usb_ftdi/ftdiexceptions.cpp) diff --git a/src/examples/CMakeLists.txt b/src/examples/CMakeLists.txt index 2f64dc6..171b454 100644 --- a/src/examples/CMakeLists.txt +++ b/src/examples/CMakeLists.txt @@ -45,3 +45,15 @@ ADD_EXECUTABLE(test_multiple_client test_multiple_client.cpp) # edit the following line to add the necessary libraries TARGET_LINK_LIBRARIES(test_multiple_client ${IRIUTILS_LIBRARY} comm pthread) + +# edit the following line to add the source code for the example and the name of the executable +ADD_EXECUTABLE(test_udp_rx test_simple_client_udp_rx.cpp) + +# edit the following line to add the necessary libraries +TARGET_LINK_LIBRARIES(test_udp_rx ${IRIUTILS_LIBRARY} comm pthread) + +# edit the following line to add the source code for the example and the name of the executable +ADD_EXECUTABLE(test_udp_tx test_simple_client_udp_tx.cpp) + +# edit the following line to add the necessary libraries +TARGET_LINK_LIBRARIES(test_udp_tx ${IRIUTILS_LIBRARY} comm pthread) diff --git a/src/examples/test_simple_client.cpp b/src/examples/test_simple_client.cpp index 488d181..92904e0 100644 --- a/src/examples/test_simple_client.cpp +++ b/src/examples/test_simple_client.cpp @@ -1,7 +1,7 @@ #include "socketclient.h" #include "socketexceptions.h" -std::string server_ip="192.168.0.13"; +std::string server_ip="192.168.100.97"; int server_port=6653; int main(int argc,char *argv[]) diff --git a/src/examples/test_simple_client_udp_rx.cpp b/src/examples/test_simple_client_udp_rx.cpp new file mode 100755 index 0000000..220d6de --- /dev/null +++ b/src/examples/test_simple_client_udp_rx.cpp @@ -0,0 +1,32 @@ +#include "socketudp.h" +#include "socketexceptions.h" + +std::string server_ip="192.168.100.97"; +int server_port=6653; + +int main(int argc,char *argv[]) +{ + TSocket_info info; + CSocketUDP client("client"); + unsigned char answer[5]; + + try{ + info.address=server_ip; + info.port=server_port; + client.open(&info); + client.config(NULL); + std::cout << "connected." << std::endl; + while(1) + { + std::cout << "receiving data ..." << std::endl; + client.read(answer,5); + std::cout << "data received: " << answer << std::endl; + sleep(1); + } + std::cout << "closing connection ..." << std::endl; + client.close(); + sleep(1); + }catch(CException &e){ + std::cout << e.what() << std::endl; + } +} diff --git a/src/examples/test_simple_client_udp_tx.cpp b/src/examples/test_simple_client_udp_tx.cpp new file mode 100755 index 0000000..32f5bf0 --- /dev/null +++ b/src/examples/test_simple_client_udp_tx.cpp @@ -0,0 +1,29 @@ +#include "socketudp.h" +#include "socketexceptions.h" + +std::string server_ip="192.168.100.97"; +int server_port=6653; + +int main(int argc,char *argv[]) +{ + TSocket_info info; + CSocketUDP client("client"); + unsigned char msg[5]="hola"; + + try{ + client.open(); + client.config(); + std::cout << "connected." << std::endl; + while(1) + { + std::cout << "sending data ..." << std::endl; + client.write_to(server_ip,server_port,msg,5); + sleep(1); + } + std::cout << "closing connection ..." << std::endl; + client.close(); + sleep(1); + }catch(CException &e){ + std::cout << e.what() << std::endl; + } +} diff --git a/src/examples/test_simple_server.cpp b/src/examples/test_simple_server.cpp index 4c6a7a2..aa2f09b 100644 --- a/src/examples/test_simple_server.cpp +++ b/src/examples/test_simple_server.cpp @@ -2,8 +2,8 @@ #include "socketserver.h" #include "eventserver.h" -std::string server_IP_address="127.0.0.1"; -int server_port=2012; +std::string server_IP_address="192.168.100.97"; +int server_port=6653; int num_listen=1; int main(int argc,char *argv[]) diff --git a/src/sockets/socket.cpp b/src/sockets/socket.cpp index 1a28c3a..71bf457 100644 --- a/src/sockets/socket.cpp +++ b/src/sockets/socket.cpp @@ -1,14 +1,16 @@ #include "socket.h" #include "socketexceptions.h" #include <string.h> +#include "errno.h" -CSocket::CSocket(const std::string &comm_id) : CComm(comm_id) +CSocket::CSocket(const std::string &comm_id,socket_type_t type) : CComm(comm_id) { this->connection_closed_event.clear(); this->connection_closed_event+=comm_id; this->connection_closed_event+="_closed"; this->event_server->create_event(this->connection_closed_event); this->cloned=false; + this->type=type; } CSocket::CSocket(const std::string &comm_id,const int fd) : CComm(comm_id) @@ -49,19 +51,27 @@ void CSocket::hard_open(void *comm_dev) if(!this->cloned) { - if((this->socket_fd=socket(AF_INET,SOCK_STREAM,0))<0) + if(this->type==socket_tcp) { - /* handle exceptions */ - throw CSocketException(_HERE_,"Error opening socket", this->comm_id); + if((this->socket_fd=socket(AF_INET,SOCK_STREAM,0))<0) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"Error opening socket", this->comm_id); + } } else { - if(setsockopt(this->socket_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))<0) + if((this->socket_fd=socket(AF_INET,SOCK_DGRAM,0))<0) { /* handle exceptions */ - throw CSocketException(_HERE_,"Impossible to change socket options",this->comm_id); + throw CSocketException(_HERE_,"Error opening socket", this->comm_id); } } + if(setsockopt(this->socket_fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(int))<0) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"Impossible to change socket options",this->comm_id); + } } } @@ -94,6 +104,7 @@ int CSocket::hard_write(unsigned char *data, int len) { if((num_write=::write(this->socket_fd,data,len))==-1) { + std::cout << errno << std::endl; /* handle exceptions */ throw CSocketException(_HERE_,"Error while writing to the socket.",this->comm_id); } @@ -129,6 +140,7 @@ int CSocket::hard_wait_comm_event(void) FD_ZERO(&error_set); FD_SET(this->socket_fd,&error_set); wait_result=select(max_fd,&receive_set,NULL,&error_set,NULL); + std::cout << "new data" << std::endl; if(wait_result==-1) { /* handle exceptions */ @@ -165,6 +177,11 @@ void CSocket::hard_close(void) this->cloned=false; } +socket_type_t CSocket::get_socket_type(void) +{ + return this->type; +} + CSocket::~CSocket() { this->close(); diff --git a/src/sockets/socket.h b/src/sockets/socket.h index 89f1763..3684084 100644 --- a/src/sockets/socket.h +++ b/src/sockets/socket.h @@ -40,6 +40,8 @@ typedef struct { int port; }TSocket_info; +typedef enum {socket_tcp=0,socket_udp=1} socket_type_t; + /** * \brief Socket driver * @@ -86,6 +88,11 @@ class CSocket : public CComm * not be accessed from the outside. */ bool cloned; + /** + * \brief + * + */ + socket_type_t type; protected: /** * \brief socket file descriptor. @@ -293,7 +300,7 @@ class CSocket : public CComm * unique identifier for all the threads and events of the * class. */ - CSocket(const std::string &comm_id); + CSocket(const std::string &comm_id,socket_type_t type=socket_tcp); /** * \brief Function to get the name of Connection Closed Event * @@ -310,6 +317,11 @@ class CSocket : public CComm * functions of the CEventServer class to wait its activation. */ std::string get_connection_closed_event(void); + /** + * \brief + * + */ + socket_type_t get_socket_type(void); /** * \brief Destructor * diff --git a/src/sockets/socketclient.cpp b/src/sockets/socketclient.cpp index efb63cf..dc25cbc 100644 --- a/src/sockets/socketclient.cpp +++ b/src/sockets/socketclient.cpp @@ -2,7 +2,7 @@ #include "socketexceptions.h" #include <string.h> -CSocketClient::CSocketClient(const std::string &sock_id) : CSocket(sock_id) +CSocketClient::CSocketClient(const std::string &sock_id) : CSocket(sock_id,socket_tcp) { this->connected=false; this->remote.address.clear(); diff --git a/src/sockets/socketudp.cpp b/src/sockets/socketudp.cpp new file mode 100755 index 0000000..8eb2c82 --- /dev/null +++ b/src/sockets/socketudp.cpp @@ -0,0 +1,77 @@ +#include "socketudp.h" +#include "socketexceptions.h" + +CSocketUDP::CSocketUDP(const std::string &sock_id) : CSocket(sock_id,socket_udp) +{ + this->receive.port=-1; + this->receive.address.clear(); +} + +void CSocketUDP::hard_open(void *comm_dev) +{ + TSocket_info *remote=(TSocket_info *)comm_dev; + sockaddr_in sock; + + CSocket::hard_open(NULL); + if(remote!=NULL) + { + memset(&sock,0,sizeof(sock)); + sock.sin_family=AF_INET; + if(inet_aton(remote->address.c_str(),&sock.sin_addr)==0) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"Impossible to convert IP address",this->comm_id); + } + else + { + sock.sin_port=htons(remote->port); + // bind to the desired IP and port to receive data from + if((::bind(this->socket_fd,(struct sockaddr *)&sock,sizeof(sock)))<0) + { + /* handle exceptions */ + throw CSocketException(_HERE_, "Error with connect function", this->comm_id); + } + else + { + this->receive.port=remote->port; + this->receive.address=remote->address; + } + } + } +} + +void CSocketUDP::hard_close(void) +{ + CSocket::hard_close(); + this->receive.port=-1; + this->receive.address.clear(); +} + +int CSocketUDP::write_to(std::string &ip,int port,unsigned char *data,int len) +{ + sockaddr_in sock; + int written=0; + + memset(&sock,0,sizeof(sock)); + sock.sin_family=AF_INET; + if(inet_aton(ip.c_str(),&sock.sin_addr)==0) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"Impossible to convert IP address",this->comm_id); + } + else + { + sock.sin_port=htons(port); + if((written=sendto(this->socket_fd,data,len,0,(struct sockaddr *)&sock,sizeof(sock)))<0) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"Impossible to send data to the desired IP and port",this->comm_id); + } + return written; + } +} + +CSocketUDP::~CSocketUDP() +{ + +} diff --git a/src/sockets/socketudp.h b/src/sockets/socketudp.h new file mode 100755 index 0000000..352f70e --- /dev/null +++ b/src/sockets/socketudp.h @@ -0,0 +1,57 @@ +#ifndef _SOCKETUDP_H_ +#define _SOCKETUDP_H_ + +#include "socket.h" + +class CSocketUDP : public CSocket +{ + private: + TSocket_info receive; + protected: + /** + * \brief Connect function + * + * This function is called when the base class open() function is called, and + * it is used to perform the connection to a server. This function requires a + * TSocket_info structure as parameter which must be provided to the open() + * call. It also calls the hard_open() function of the CSocket class to + * initialize the base class attributes. + * + * The IP address and port within this structure are used to try to stablish + * a communication with a remote server. If the server is already listening, + * the function returns normally with all the internal attributes properly + * initialized. + * + * If the server is not yet listening, this function throws a CSocketNoConnection + * exception. This exception can be catched and used to iterate the process + * until the server is available or terminate the applcation. In case of any + * other error, this function throws a CSocketException. + * + * After the connection is set, it is still necessary to call the config() + * function to properly configure the object to send and receive information. + * + * \param comm_dev a valid pointer to a TSocket_info structure with the IP + * address and listening port of the desired server. See the + * documentation on the TSocket_info structure for more + * information on the IP address and port format. + */ + virtual void hard_open(void *comm_dev=NULL); + /** + * \brief function to close the client socket + * + * This function is called when the close() function of the base class is + * called. It calls the hard_close() function of the CSocket class to + * actually terminate the connection and change all the internal attributes + * to reflect that (the connection flag is set back to false and the server + * IP address and port are set to the default values. + * + * In case of any error, this function throws a CSocketException. + */ + virtual void hard_close(void); + public: + CSocketUDP(const std::string &sock_id); + int write_to(std::string &ip,int port,unsigned char *data,int len); + ~CSocketUDP(); +}; + +#endif -- GitLab