diff --git a/src/examples/test_simple_client_udp_rx.cpp b/src/examples/test_simple_client_udp_rx.cpp index 220d6de5cde22c9b7346ecc61578963de1ee1bbb..120437ce963ffb7d7ede19a2b854f592d6a215c2 100755 --- a/src/examples/test_simple_client_udp_rx.cpp +++ b/src/examples/test_simple_client_udp_rx.cpp @@ -2,26 +2,30 @@ #include "socketexceptions.h" std::string server_ip="192.168.100.97"; -int server_port=6653; +int server_port=49152; int main(int argc,char *argv[]) { + CEventServer *event_server=CEventServer::instance(); + int num=0; TSocket_info info; CSocketUDP client("client"); - unsigned char answer[5]; + unsigned char msg[5]; + std::list<std::string> events; try{ info.address=server_ip; info.port=server_port; - client.open(&info); - client.config(NULL); + client.open(&server_port); + client.config(); + events.push_back(client.add_client(server_ip)); 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); + event_server->wait_all(events); + num=client.get_num_data_from(server_ip); + num=client.read_from(server_ip,msg,num); + std::cout << msg << "," << num << std::endl; } std::cout << "closing connection ..." << std::endl; client.close(); diff --git a/src/examples/test_simple_client_udp_tx.cpp b/src/examples/test_simple_client_udp_tx.cpp index 32f5bf06f8884afa183b749195dd5f09c6d6b1e9..128a400836541f25e7abb21c524a9fddf802e53a 100755 --- a/src/examples/test_simple_client_udp_tx.cpp +++ b/src/examples/test_simple_client_udp_tx.cpp @@ -2,7 +2,7 @@ #include "socketexceptions.h" std::string server_ip="192.168.100.97"; -int server_port=6653; +int server_port=49152; int main(int argc,char *argv[]) { diff --git a/src/sockets/socket.cpp b/src/sockets/socket.cpp index 71bf4570fa1e99e089b4c67ceff41a041fa5e93f..e7d97312e8e67073aac2c6c380f74cf7a1e607ec 100644 --- a/src/sockets/socket.cpp +++ b/src/sockets/socket.cpp @@ -140,7 +140,6 @@ 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 */ diff --git a/src/sockets/socketudp.cpp b/src/sockets/socketudp.cpp index 8eb2c82ceb06cbae7a66c3915755a7fd3c8163bb..59c9055ed2f1f3e01cb53ed4f6953e72e2a8871e 100755 --- a/src/sockets/socketudp.cpp +++ b/src/sockets/socketudp.cpp @@ -3,48 +3,73 @@ CSocketUDP::CSocketUDP(const std::string &sock_id) : CSocket(sock_id,socket_udp) { - this->receive.port=-1; - this->receive.address.clear(); + this->associated_port=-1; + this->clients.clear(); } void CSocketUDP::hard_open(void *comm_dev) { - TSocket_info *remote=(TSocket_info *)comm_dev; + int *port=(int *)comm_dev; sockaddr_in sock; CSocket::hard_open(NULL); - if(remote!=NULL) + if(port!=NULL) { memset(&sock,0,sizeof(sock)); sock.sin_family=AF_INET; - if(inet_aton(remote->address.c_str(),&sock.sin_addr)==0) + sock.sin_addr.s_addr=htonl(INADDR_ANY); + sock.sin_port=htons(*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_,"Impossible to convert IP address",this->comm_id); + throw CSocketException(_HERE_, "Error with connect function", this->comm_id); } else + this->associated_port=*port; + } +} + +int CSocketUDP::hard_read(unsigned char *data, int len) +{ + CEventServer *event_server=CEventServer::instance(); + unsigned int i=0; + struct sockaddr_in sock; + socklen_t sock_len=sizeof(sock); + int read=0; + + sock.sin_family=AF_INET; + if((read=recvfrom(this->socket_fd,data,len,0,(struct sockaddr *)&sock,&sock_len))<0) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"Impossible to read from the socket",this->comm_id); + } + // enqueue the data to the corresponding client + for(i=0;i<this->clients.size();i++) + if(this->clients[i]->ip_address==std::string(inet_ntoa(sock.sin_addr))) { - 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; - } + this->clients[i]->data_queue.write(data,len); + if(!event_server->event_is_set(this->clients[i]->new_data_avail_event_id)) + event_server->set_event(this->clients[i]->new_data_avail_event_id); } - } + + return read; } void CSocketUDP::hard_close(void) { + CEventServer *event_server=CEventServer::instance(); + unsigned int i; + CSocket::hard_close(); - this->receive.port=-1; - this->receive.address.clear(); + this->associated_port=-1; + for(i=0;i<this->clients.size();i++) + { + event_server->delete_event(this->clients[i]->new_data_avail_event_id); + this->clients[i]->new_data_avail_event_id=""; + this->clients[i]->ip_address=""; + } + this->clients.clear(); } int CSocketUDP::write_to(std::string &ip,int port,unsigned char *data,int len) @@ -70,7 +95,62 @@ int CSocketUDP::write_to(std::string &ip,int port,unsigned char *data,int len) return written; } } - + +int CSocketUDP::read_from(std::string &ip, unsigned char *data, int len) +{ + unsigned int i=0; + int read=0; + + for(i=0;i<this->clients.size();i++) + { + if(this->clients[i]->ip_address==ip) + { + read=this->clients[i]->data_queue.read(data,len); + return read; + } + } + // handle exceptions + throw CSocketException(_HERE_,"The given IP address is not in the allowed list",this->comm_id); +} + +int CSocketUDP::get_num_data_from(std::string &ip) +{ + unsigned int i=0; + + for(i=0;i<this->clients.size();i++) + { + if(this->clients[i]->ip_address==ip) + { + return this->clients[i]->data_queue.get_num_data(); + } + } + // handle exceptions + throw CSocketException(_HERE_,"The given IP address is not in the allowed list",this->comm_id); +} + +std::string CSocketUDP::add_client(std::string &ip) +{ + CEventServer *event_server=CEventServer::instance(); + TUDPClient *new_client=new TUDPClient; + unsigned int i=0; + + for(i=0;i<this->clients.size();i++) + { + if(this->clients[i]->ip_address==ip) + { + /* handle exceptions */ + throw CSocketException(_HERE_,"The given IP addres is alreasy accepted",this->comm_id); + } + } + // add the new IP address to wait data for + new_client->ip_address=ip; + new_client->new_data_avail_event_id=ip + "_data_avail_event_id"; + event_server->create_event(new_client->new_data_avail_event_id); + this->clients.push_back(new_client); + + return new_client->new_data_avail_event_id; +} + CSocketUDP::~CSocketUDP() { diff --git a/src/sockets/socketudp.h b/src/sockets/socketudp.h index 352f70e613a161c2e85683c3b32d1533d527dacd..2f669829117bb94c1d00f9ac7ad93ec42d3bdc5d 100755 --- a/src/sockets/socketudp.h +++ b/src/sockets/socketudp.h @@ -2,11 +2,21 @@ #define _SOCKETUDP_H_ #include "socket.h" +#include "cqueue.h" +#include <vector> + +typedef struct +{ + std::string ip_address; + std::string new_data_avail_event_id; + CQueue data_queue; +}TUDPClient; class CSocketUDP : public CSocket { private: - TSocket_info receive; + int associated_port; + std::vector<TUDPClient *> clients; protected: /** * \brief Connect function @@ -36,6 +46,32 @@ class CSocketUDP : public CSocket * information on the IP address and port format. */ virtual void hard_open(void *comm_dev=NULL); + /** + * \brief Function to actually read from the device + * + * This function is automatically called when the new data received event is + * activated. The read() function from the base class gets data from the + * internal queue, so this function is not used. It must try to read the + * ammount of data specified and store it in the data buffer provided without + * blocking. Also, it must return the number of bytes actually read from the + * devicve, since they may be different than the desired value. + * + * In case of any error, this function throws a CSocketException exception. + * + * \param data a reference to the buffer where the received data must be + * copied. The necessary memory for this buffer must be allocated before + * calling this function and have enough size to store all the desired data. + * If this buffer is not initialized, the function throws an exception. + * + * \param len a positive interger that indicates the number of byte to be + * read from the communication device. This value must be at most the length + * of the data buffer provided to the function. + * + * \return an integer with the number of bytes actually read. These number + * coincide with the desired number if there is enough data in the internal + * queue, but it could be smaller if not. + */ + virtual int hard_read(unsigned char *data, int len); /** * \brief function to close the client socket * @@ -50,7 +86,10 @@ class CSocketUDP : public CSocket virtual void hard_close(void); public: CSocketUDP(const std::string &sock_id); + std::string add_client(std::string &ip); int write_to(std::string &ip,int port,unsigned char *data,int len); + int read_from(std::string &ip, unsigned char *data, int len); + int get_num_data_from(std::string &ip); ~CSocketUDP(); };