Ingeniería del SW Junio 2009 Ejercicio 1 (25 minutos) 2.5

Anuncio
Ingeniería del SW Junio 2009
Ejercicio 1 (25 minutos) 2.5 puntos
Se desea realizar una simulación de un sistema multicuerpo de forma concurrente con hilos de
la librería <pthread.h>. Dicho sistema está definido de tal forma que el siguiente programa
permite simular 100 objetos, de forma secuencial:
void main()
{
Cuerpo objetos[100];
while(1)
{
for(int i=0;i<100;i++)
{
int choque=objetos[i].Simula();
if(choque)
cout<<"El cuerpo "<<i<<" ha colisionado"<<endl;
}
}
}
Para convertir el código anterior en concurrente:
a) El hilo principal lanzara tantos hilos como objetos tenga que simular. Cada hilo
entrara en un bucle infinito en el que simulará uno de los objetos, cuyo índice le será
pasado como parámetro al hilo en el momento de ser lanzado.
b) El hilo principal entrara después en un bucle infinito que mostrara por pantalla el
mensaje “Simulando…” cada 1 segundo.
c) Para evitar que la salida por pantalla de los hilos quede entremezclada, se realizara la
sincronización de los mismos (única y exclusivamente de la salida por pantalla)
mediante una tubería POSIX.
Ingeniería del SW Junio 2009
Cuerpo objetos[100];
int tuberia[2];
void* simula(void* d)
{
int index=*((int*)d);
while(1)
{
int choque=objetos[index].Simula();
if(choque)
{
char testigo;
read(tuberia[0],&testigo,sizeof(testigo));
cout<<"El cuerpo "<<index<<" ha colisionado"<<endl;
write(tuberia[1],&testigo,sizeof(testigo));
}
}
}
void main()
{
pipe(tuberia);
char testigo;
write(tuberia[1],&testigo,sizeof(testigo));
for(int i=0;i<100;i++)
{
pthread_create(&thid,NULL,simula,&i);
}
while(1)
{
sleep(1);
read(tuberia[0],&testigo,sizeof(testigo));
cout<<"Simulando"<<endl;
write(tuberia[1],&testigo,sizeof(testigo));
}
}
Ingeniería del SW Junio 2009
Ejercicio 2 (20 minutos) 2.0 puntos
Se desea hacer un servidor C/C++ para las reservas por internet de vuelos de una compañía
area, mediante sockets POSIX. Dicho servidor escuchara peticiones en su tarjeta de red con IP
192.168.1.1 y en el puerto 12345. Permitirá conectarse a un único cliente simultáneamente y
queda a la espera que el cliente le envíe mensajes. Mientras el cliente este conectado y envíe
mensajes, seguirá atendiendo todos los mensajes de dicho cliente. Se puede utilizar si se desea
la siguiente clase:
class Socket
{
public:
Socket();
virtual ~Socket();
int Connect(char ip[],int port); //Conectar un cliente
//Inicializar un servidor (encapsula la creacion del socket, el bind y el
//listen
int InitServer(char ip[],int port);
Socket Accept(); //encapsula el accept(), y es bloqueante
void Close();
int Send(char cad[],int length); //devuelve -1 en caso de error
int Receive(char cad[],int length);//devuelve -1 en caso de error
private:
int sock;
};
El servidor puede recibir mensajes de petición de información, de reserva y de cancelación.
Un mensaje de petición recibido por el servidor tendrá el siguiente formato (CONSULTA
Origen Destino Dia Mes Año) y será respondido con (DISPONIBLE Identificador). Para
realizar la reserva el cliente enviara un mensaje (RESERVA Identificador NumeroTarjeta) y
el servidor responderá (RESERVADO Localizador). A continuación se muestra un ejemplo
de una operación completa:
Cliente->Servidor
Servidor->Cliente
Cliente->Servidor
Servidor->Cliente
CONSULTA Madrid Hawai 30 06 2009
DISPONIBLE 012345
RESERVA 012345 11111111111
RESERVADO XDFG56
No es necesaria ninguna gestión de errores, exceptuando la desconexión del cliente. Cuando
se desconecta un cliente, el servidor queda a la espera de una nueva conexión.
Supóngase que se dispone de las siguientes funciones que manejan las bases de datos:
// La función devuelve un número entero, que es el identificador del vuelo
int Consulta(char origen[], char destino[], int dia, int mes, int año);
// La función admite un identificador y devuelve una cadena “localizador”
void Reserva(int identificador, char localizador[]);
Ingeniería del SW Junio 2009
//SOLUCION:
#include "Socket.h"
void main()
{
Socket server,client;
server.InitServer("192.168.1.1",12345);
while(1)
{
client=server.Accept();
char buffer[500];
while(1)
{
if(-1==client.Receive(buffer,500))
break;
char com[100];
sscanf(buffer,"%s",com);
if(!strcmp(com,"CONSULTA"))
{
char origen[100],destino[100];
int dia,mes,agno;
sscanf(buffer,"%s %s %s %d %d %d",com,origen,destino,dia,mes,agno);
int vuelo=Consulta(origen,destino,dia,mes,agno);
char resp[200];
sprintf(resp,"DISPONIBLE %d",vuelo);
client.Send(resp,strlen(resp)+1);
}
if(!strcmp(com,"RESERVA"))
{
char localizador[100];
int vuelo;
sscanf(buffer,"%s %d",com,vuelo);
Reserva(vuelo,localizador);
char resp[200];
sprintf(resp,"RESERVADO %s",localizador);
client.Send(resp,strlen(resp)+1);
}
}
client.Close();
}
Ingeniería del SW Junio 2009
Ejercicio 3 (25 minutos) 2.5 puntos
A) Impleméntese un procedimiento recursivo para mostrar en pantalla un número entero
positivo en formato binario. Un ejemplo de sesión en un shell (para un ejecutable denominado
conversor) sería:
Entrada: conversor 32
Entrada: conversor 64
Salida: 10000
Salida: 100000
Nota: La manera más simple de realizar la tarea es ir dividiendo por dos el dato. Cada digito
del número binario buscado es el resto de esa división entera. (Por ejemplo 13 en binario:
13/2 = 6; 13%2=1 // 6/2=3; 6%2=0 // 3/2 =1; 3%2=1; // 1; La conversión es 0x1101. Nótese
que hay que reconstruir los restos al revés).
B) Impleméntese un procedimiento que recursivamente genere los N primeros términos de la
sucesión de Fibonacci, cuya definición implícita es xn = xn−1 + xn−2 ( x0 = 0, x1 = 1) .
A)
#include <iostream.h>
//#include <stdio.h>
#include <stdlib.h>
void binario(int i){
if(i==1) cout<<"1";
else {
binario(i/2);
cout<<i%2;
//Tiene que ir después de la llamada recursiva
}
}
void main(int argc, char** argv){
if(argc!=2)
cout<<"Error en el numero de parámetros";
binario(atoi(argv[1]));
cout<<endl;
}
B)
#include <iostream.h>
#define N 10
int Rec(int n){
if(n = = 0) return 0;
if(n = = 1) return 1;
return(Rec(n-1)+Rec(n-2));
}
void main(){
for(int i=0; i<N; i++)
cout<<"("<<i<<")"<<Rec(i)<<endl;
}
Descargar