diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index ab896393d923110ab91b576c873b128314f1dd71..51fc5168670c26863f4646bf0c6822dad95b9c1e 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 2f64dc6df46887e61623f5955f9986e1a3987c5e..171b454c57205a30eb0205974af92b2d15e5cb34 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 488d1815826140682f5819b9a26d8e6f389ab0f9..92904e0643f81734ba0d525380faaf33f0cd5d0a 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 0000000000000000000000000000000000000000..220d6de5cde22c9b7346ecc61578963de1ee1bbb --- /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 0000000000000000000000000000000000000000..32f5bf06f8884afa183b749195dd5f09c6d6b1e9 --- /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 4c6a7a2fe2c09d3ccc23e9c295e66dfd246b752f..aa2f09bb84ccff4e539dc73ac4e54dfc1aa2db83 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 1a28c3a000c791bdd81b38cf43a15d29c93a36dc..71bf4570fa1e99e089b4c67ceff41a041fa5e93f 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 89f1763f23aa287c12e0936db0d3d486504af0ad..36840841d34a3c1db216ff96d32a144044f01efb 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 efb63cf52119da6e5dc075deb640c9d4f76343a0..dc25cbcba860763f8fd1c115635854fa6ba11268 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 0000000000000000000000000000000000000000..8eb2c82ceb06cbae7a66c3915755a7fd3c8163bb --- /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 0000000000000000000000000000000000000000..352f70e613a161c2e85683c3b32d1533d527dacd --- /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