Skip to content
Snippets Groups Projects
Commit f0a95810 authored by Sergi Hernandez's avatar Sergi Hernandez
Browse files

Completed the UDP class.

Changed the UDP examples.
parent f2a7f283
No related branches found
No related tags found
No related merge requests found
...@@ -2,26 +2,30 @@ ...@@ -2,26 +2,30 @@
#include "socketexceptions.h" #include "socketexceptions.h"
std::string server_ip="192.168.100.97"; std::string server_ip="192.168.100.97";
int server_port=6653; int server_port=49152;
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {
CEventServer *event_server=CEventServer::instance();
int num=0;
TSocket_info info; TSocket_info info;
CSocketUDP client("client"); CSocketUDP client("client");
unsigned char answer[5]; unsigned char msg[5];
std::list<std::string> events;
try{ try{
info.address=server_ip; info.address=server_ip;
info.port=server_port; info.port=server_port;
client.open(&info); client.open(&server_port);
client.config(NULL); client.config();
events.push_back(client.add_client(server_ip));
std::cout << "connected." << std::endl; std::cout << "connected." << std::endl;
while(1) while(1)
{ {
std::cout << "receiving data ..." << std::endl; event_server->wait_all(events);
client.read(answer,5); num=client.get_num_data_from(server_ip);
std::cout << "data received: " << answer << std::endl; num=client.read_from(server_ip,msg,num);
sleep(1); std::cout << msg << "," << num << std::endl;
} }
std::cout << "closing connection ..." << std::endl; std::cout << "closing connection ..." << std::endl;
client.close(); client.close();
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
#include "socketexceptions.h" #include "socketexceptions.h"
std::string server_ip="192.168.100.97"; std::string server_ip="192.168.100.97";
int server_port=6653; int server_port=49152;
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {
......
...@@ -140,7 +140,6 @@ int CSocket::hard_wait_comm_event(void) ...@@ -140,7 +140,6 @@ int CSocket::hard_wait_comm_event(void)
FD_ZERO(&error_set); FD_ZERO(&error_set);
FD_SET(this->socket_fd,&error_set); FD_SET(this->socket_fd,&error_set);
wait_result=select(max_fd,&receive_set,NULL,&error_set,NULL); wait_result=select(max_fd,&receive_set,NULL,&error_set,NULL);
std::cout << "new data" << std::endl;
if(wait_result==-1) if(wait_result==-1)
{ {
/* handle exceptions */ /* handle exceptions */
......
...@@ -3,48 +3,73 @@ ...@@ -3,48 +3,73 @@
CSocketUDP::CSocketUDP(const std::string &sock_id) : CSocket(sock_id,socket_udp) CSocketUDP::CSocketUDP(const std::string &sock_id) : CSocket(sock_id,socket_udp)
{ {
this->receive.port=-1; this->associated_port=-1;
this->receive.address.clear(); this->clients.clear();
} }
void CSocketUDP::hard_open(void *comm_dev) void CSocketUDP::hard_open(void *comm_dev)
{ {
TSocket_info *remote=(TSocket_info *)comm_dev; int *port=(int *)comm_dev;
sockaddr_in sock; sockaddr_in sock;
CSocket::hard_open(NULL); CSocket::hard_open(NULL);
if(remote!=NULL) if(port!=NULL)
{ {
memset(&sock,0,sizeof(sock)); memset(&sock,0,sizeof(sock));
sock.sin_family=AF_INET; 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 */ /* handle exceptions */
throw CSocketException(_HERE_,"Impossible to convert IP address",this->comm_id); throw CSocketException(_HERE_, "Error with connect function", this->comm_id);
} }
else 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); this->clients[i]->data_queue.write(data,len);
// bind to the desired IP and port to receive data from if(!event_server->event_is_set(this->clients[i]->new_data_avail_event_id))
if((::bind(this->socket_fd,(struct sockaddr *)&sock,sizeof(sock)))<0) event_server->set_event(this->clients[i]->new_data_avail_event_id);
{
/* handle exceptions */
throw CSocketException(_HERE_, "Error with connect function", this->comm_id);
}
else
{
this->receive.port=remote->port;
this->receive.address=remote->address;
}
} }
}
return read;
} }
void CSocketUDP::hard_close(void) void CSocketUDP::hard_close(void)
{ {
CEventServer *event_server=CEventServer::instance();
unsigned int i;
CSocket::hard_close(); CSocket::hard_close();
this->receive.port=-1; this->associated_port=-1;
this->receive.address.clear(); 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) 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) ...@@ -70,7 +95,62 @@ int CSocketUDP::write_to(std::string &ip,int port,unsigned char *data,int len)
return written; 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() CSocketUDP::~CSocketUDP()
{ {
......
...@@ -2,11 +2,21 @@ ...@@ -2,11 +2,21 @@
#define _SOCKETUDP_H_ #define _SOCKETUDP_H_
#include "socket.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 class CSocketUDP : public CSocket
{ {
private: private:
TSocket_info receive; int associated_port;
std::vector<TUDPClient *> clients;
protected: protected:
/** /**
* \brief Connect function * \brief Connect function
...@@ -36,6 +46,32 @@ class CSocketUDP : public CSocket ...@@ -36,6 +46,32 @@ class CSocketUDP : public CSocket
* information on the IP address and port format. * information on the IP address and port format.
*/ */
virtual void hard_open(void *comm_dev=NULL); 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 * \brief function to close the client socket
* *
...@@ -50,7 +86,10 @@ class CSocketUDP : public CSocket ...@@ -50,7 +86,10 @@ class CSocketUDP : public CSocket
virtual void hard_close(void); virtual void hard_close(void);
public: public:
CSocketUDP(const std::string &sock_id); 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 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(); ~CSocketUDP();
}; };
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment