PracticaT1 - POO - y - C++ Sockets

Descargar como pdf o txt
Descargar como pdf o txt
Está en la página 1de 5

1

Aplicaciones y Servicios
Grado en Ingeniera Telemtica
ETSI Telecomunicacin. Mlaga

PR!TI!A T".# Programacin orientada a o$%etos en !&&
En esta prctica se pretende realizar una encapsulacin en C++ de la interfaz sockets de C, de
forma que se eliminen algunas tareas tediosas y repetitivas para el programador, a la vez que
se reducen los posibles errores de uso de la librera en tiempo de eecucin!
"e forma didctica, se proponen varias clases#
$net%ddress Encapsula la estructura sockadd&in y su
maneo
'ocket(ase Clase base de sockets! Contiene el descriptor
de socket y algunos m)todos comunes a
todas las clases derivadas
'ocket'tream Clase derivada de 'ocket(ase, especializada
en sockets detipo *C+
'ocket"atagram Clase derivada de 'ocket(ase, especializada
en sockets de tipo ,"+
'ocketClient Clase derivada de 'ocket'tream,
especializada en las operaciones de un cliente
*C+
'ocket'erver Clase derivada de 'ocket'tream,
especializada en las operaciones de un
servidor *C+

Como una imagen vale ms que mil palabras, a continuacin se muestra cmo quedara el
cdigo de un cliente y un servidor *C+ si se utilizan estas clases y se ocultan las llamadas a la
librera de sockets de bao nivel!
C-$E.*E#
#include "socket.h"

int main(){
InetAddress serv_addr(50000,"127.0.0.1"); //puerto 50000
SocketClient cliente;
if (cliente.connect(serv_addr) == 0){ //Ok
cliente.send("Hola mundo",11);
}
return 0;
}
'E/0$"1/#
#include <iostream>
#include "socket.h"

int main(){
SocketServer servidor(50000); //puerto 50000
2

SocketStream * cliente = servidor.accept();
if(cliente != NULL){
char buffer[50];
int recibidos = cliente->recv(buffer,50);
if(recibidos > 0){
buffer[recibidos] = '\0'; //por precaucion y porque
es texto imprimible por pantalla
std::cout << "Recibido: " << buffer << std::endl;
}
delete cliente; //si no lo voy a utilizar mas
}
return 0;
}
% modo de gua, se suministra una posible definicin de dic3as clases! 'i en alg4n momento,
durante la implementacin, se requiere realizar cambios en algunas de ellas 5constructores,
m)todos, atributos6, bastar con documentar dic3os cambios en un arc3ivo C%7($1'!t8t
/**
Encapsulacion de sockets en C++
version con soporte de excepciones
**/

#ifndef __SOCKETS_CPP__
#define __SOCKETS_CPP__

#include <stdint.h>
#include <string>
#include <stdexcept>

#ifdef WIN32
#include <winsock2.h>
#define close closesocket
#else
#include <sys/socket.h>
#include <netinet/in.h>
#endif


/*
* Clase especial de excepciones para sockets
*/
class SocketException: public std::runtime_error{
public:
SocketException(const char * mensaje):
runtime_error(std::string(mensaje)){ }
};

/*
* Clase que encapsula el tedioso uso de sockaddr_in
*/
class InetAddress{
private:
std::string hostname;
struct sockaddr_in addr;
uint8_t port_;

public:
//Constructor rellena el miembro addr y port_. La direccion IP
se pasa como cadena de caracteres, ejemplo: "127.0.0.1"
9

InetAddress(uint16_t port, const char* name=0);
//No hace nada
~InetAddress(void) {}
//cambiar el puerto en port_ y en addr
void setPort(int port);
//devuelve el valor de port_
int getPort(void) const;
//devuelve un copia del miembro addr
sockaddr_in getAddress(void) const { return addr; }
//devuelve el tamano en sizeof de sockaddr_in
int getSize(void) const;
//permite comparar si dos direcciones son iguales
int operator ==(InetAddress& Address) const;
//permite comparar si dos direcciones son distintas
int operator !=(InetAddress& address) const { return
!(operator ==(address)); }
//devuelve el nombre del host (la direccion IP)
const char * getHost(void);
};

//El tipo ProtocolType sirve para encapsular las constantes
SOCK_STREAM y SOCK_DGRAM
typedef enum { Stream=SOCK_STREAM, Datagram=SOCK_DGRAM } ProtocolType;
/*
* Clase comun a todos los sockets
*/
class SocketBase{
protected:
int sd; //descriptor del socket en el sistema operativo
public:
//Constructor: hace la llamada al sistema socket() y lo almacena
en sd
SocketBase(ProtocolType protocol);
//Constructor: le pasan un descriptor de socket ya existente. No
hace la llamada a socket()
SocketBase(int nsd) : sd(nsd) { }
//Destructor: hace close del descriptor de socket
virtual ~SocketBase(void);

//Realiza la funcion bind de sockets
int bind(InetAddress& addr);
//cierra la comunicacion en sentido entrante
void closeInput(void) const { shutdown(sd, 0); }
//cierra la comunicacion en sentido saliente
void closeOutput(void) const { shutdown(sd, 1); }
};

/*
* Clase para los sockets de tipo TCP
*/
class SocketStream: public SocketBase{
public:
//Constructor: llama a SocketBase para TCP
SocketStream(void): SocketBase(Stream){}
//Constructor: llama a SocketBase con el constructor alternativo
SocketStream(int socketDescriptor):
SocketBase(socketDescriptor){}
//Destructor: no hace nada
virtual ~SocketStream(void){}
//funcion de envio de mensajes sin garantia de que se han
entregado al nivel de transporte
:

int send(const char * msg, size_t n, int options=0) const;
//funcion de envio de mensajes CON garantia de que se han
entregado al nivel de transporte
int send_n(const char * msg, size_t n, int options=0) const;
//funcion de recepcion de mensajes. Como limite se reciben n
bytes
int recv(char *msg, size_t n, int options=0) const;
//funcion de recepcion de mensajes de, exactamente, n bytes
int recv_n(char *msg, size_t n, int options=0) const;
};

/*
* Clase para los sockets de tipo TCP activo (clientes!)
*/
class SocketClient: public SocketStream{
public:
//Constructor: llama a SocketStream
SocketClient(void): SocketStream(){}
//Constructor: llama a SocketStream y realiza la llamada al
sistema connect()
SocketClient(InetAddress& host);
//Desctructor: no hace nada especial
virtual ~SocketClient(void){}

//realiza la llamada al sistema connect(). Solo se llama si se
ha utilizado el constructor por defecto!
int connect(InetAddress& addr);
};


/*
* Clase para los sockets de tipo TCP pasivo (servidores!)
*/
class SocketServer: public SocketStream{
public:
//Constructor: llama al constructor de SocketStream. Luego hace
el bind, y listen. Para listen usa el argumento backlog
SocketServer(uint16_t port, int backlog=15);
//Destructor: no hace nada en especial
virtual ~SocketServer(void);
//funcion que realiza el accept y luego crea en heap un
SocketStream con el id. de socket conectado
SocketStream * accept(void);
};

/*
* Clase para los sockets de tipo UDP
*/
class SocketDatagram: public SocketBase{
public:
//Constructor por defecto. Llama a SocketBase con ProtocolType
datagrama. Pide un puerto libre al sistema operativo y hace bind
//NOTA: si el puerto es cero, el S.O. asigna uno libre a partir
del 1024.
SocketDatagram(void);
//Constructor que proporciona la direccion y o puerto donde
hacer el bind
SocketDatagram(InetAddress& mia);
//Destructor que no hace nada
virtual ~SocketDatagram(void){}
//funcion de envio a una direccion determinada
;

int send(const InetAddress& addr, const char * msg, size_t n,
int options=0) const;
//funcion de recepcion desde una direccion que devuelve por
referencia
int recv(InetAddress& addr, char * msg, size_t n, int
options=0) const;
};

#endif

También podría gustarte