Departamento de Informática Grado en Ingeniería

Anuncio
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Ejercicio 1.
Cliente.c
#include <sys/types.h>
#include <sys/socket.h>
void main(int argc, char **argv) // en argv[1] == servidor
{
int sd;
struct sockaddr_in server_addr;
struct hostent *hp;
if (argc != 2){
printf("Uso: client <direccion_servidor> \n");
exit(0);
}
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bzero((char *)&server_addr, sizeof(server_addr));
hp = gethostbyname (argv[1]);
memcpy (&(server_addr.sin_addr), hp->h_addr, hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4200);
// se establece la conexión
connect(sd, (struct sockaddr *) &server_addr, sizeof(server_addr));
// recibe la respuesta
tm now;
bzero(now, sizeof(tm));
recibir(sd, now, sizeof(tm));
printf("Date is %d/%02d/%02d\n",
now->tm_year+1900,
now->tm_mon+1, now->tm_mday);
printf("Time is %02d:%02d\n", now->tm_hour, now->tm_min);
close (sd);
exit(0);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Servidor.c
#include <sys/types.h>
#include <sys/socket.h>
#include <time.h>
void main(int argc, char *argv[])
{
struct sockaddr_in server_addr, client_addr;
int sd, sc;
int size, val;
int size;
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
val = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(int));
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(4200);
bind(sd, &server_addr, sizeof(server_addr));
listen(sd, 5);
size = sizeof(client_addr);
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
time_t tim=time(NULL);
tm *now=localtime(&tim);
enviar(sc, now, sizeof(tm));
// envía el resultado
close(sc);
// cierra la conexión (sc)
}
close (sd);
exit(0);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Ejercicio 2
Cliente.c
int mq_open(char *queue_name, int flags){
int sd;
struct sockaddr_in server_addr;
struct hostent *hp;
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
bzero((char *)&server_addr, sizeof(server_addr));
hp = gethostbyname (queue_name);
memcpy (&(server_addr.sin_addr), hp->h_addr, hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(4200);
// se establece la conexión
connect(sd, (struct sockaddr *) &server_addr, sizeof(server_addr));
}
int mq_close(int queue){
int op = OP_END;
enviar(sd, &op, sizeof(int));
close(sd);
}
int mq_send(int sd, char *data, size_t len, int prio){
int op = OP_SEND;
enviar(sd, &op, sizeof(int));
enviar(sd, &prio, sizeof(int));
enviar(sd, &len, sizeof(int));
enviar(sd, data, len);
return 0;
}
int mq_receive(int sd, char *data, size_t *len, int *prio){
int op = OP_RECV;
enviar(sd, &op, sizeof(int));
recibir (sd, &prio, sizeof(int));
recibir(sd, &len, sizeof(int));
recibir(sd, data, len);
return 0;
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Servidor.c
void main(int argc, char *argv[])
{
struct sockaddr_in server_addr, client_addr;
int sd, sc;
int size, val;
int size;
int num[2], res;
sd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
val = 1;
setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char *) &val, sizeof(int));
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(4200);
bind(sd, &server_addr, sizeof(server_addr));
listen(sd, 5);
size = sizeof(client_addr);
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
tratar_peticion(sc);
}
close (sd);
exit(0);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
void tratar_peticion(void *value){
int sc = (int)value;
do{
recibir(sd, &op, sizeof(int));
switch(op){
case OP_SEND:
recibir(sd, &prio, sizeof(int));
recibir (sd, &len, sizeof(int));
recibir (sd, data, len);
insertar (prio, data, len);
break;
case OP_RECV:
obtener (&prio, data, len);
enviar(sd, &prio, sizeof(int));
enviar (sd, &len, sizeof(int));
enviar (sd, data, len);
break;
}
}while(op!=OP_END);
close(sc);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Ejercicio 3
a)
TCP. Para evitar perdida de datos.
b)
El cliente (se encuentra en la maquina local) realiza las siguientes funciones:
• Interfaz del usuario.
• Enviar los mandatos introducidos por el usuario.
• Recibir el resultado de las operaciones y los muestra por pantalla.
El servidor (se encuentra en la maquina remota):
• Recoge las peticiones del cliente.
• Ejecuta el mandato
• Devuelve el resultado al cliente
c)
Los mensajes que se enviarán serán:
• Tamaño de los datos (4 bytes).
• Datos o texto (sin tamaño determinado).
El cliente genera el mensaje, a través de la interfaz de usuario y muestra el resultado
de la petición.
El servidor recibe y ejecuta el mandato.
d)
Cliente.c
sd = conectar();
while (leer_cadena(shell) ¡= EOF){
len = strlen(shell);
enviar(sd,&len, sizeof(int));
enviar(sd, shell, len);
recibir(sd,&len, sizeof(int));
recibir(sd, shell, len);
imprimir(shell, len);
}
close(sd);
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Servidor.c
socket(…);
bind(…);
listen(…),
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
tratar_peticion(sc);
}
close (sd);
exit(0);
}
void tratar_peticion(sc) {
char data [MAXDATA];
recibir(sd,&len, sizeof(int));
recibir(sd, shell, len);
system(shell > foo);
stat (foo, &st);
enviar(sd,&st.st_size, sizeof(int));
size = 0;
fd = open(foo)
data_len = MAXDATA;
while(st.st_size < size){
if (size+data_len > st.st_size )
data_len = st.st_size - size;
s = leer(fd, data, data_len)
enviar(sd, data, s);
size += s;
}
close(fd);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Ejercicio 4.
a)
TCP. Ya que es importante la fiabilidad y el orden de los mensajes.
b)
Existen 3 tipos de servicios:
• CC
• Puertas
• Maquinas (de pago)
Los pasos son los siguientes:
• INICIO:
o El CC (cliente) envía un mensaje de operación = LIBRE (1 byte) a las
puertas (servidor). No hay respuesta.
• FIN:
o El CC (cliente) envía un mensaje de operación = CERRADO (1 byte) a las
puertas (servidor). No hay respuesta.
• Coche que quiere entrar en el parking:
o El CC recibe el mensaje de la puerta.
• Operación: 1byte -> ENTRAR
• Fecha: 1 byte por día, mes, año (+año 2000), hora , minutos, y
segundos (total 6 bytes)
• 8 bytes matricula.
Respuesta:
• OK (1 byte) + estructura fecha + matricula (15 bytes).
Se puede generar un mensaje nuevo desde el CC a las puertas:
• OCUPADO.
•
Coche que quiere salir en el parking:
o Genera un mensaje de LIBRE que se envía a todas las puertas.
•
Coche que quiere pagar en el parking:
Mensajes desde taquilla al CC:
• Enviado:
o Operación: 1byte -> PAGAR
o Fecha: 1 byte por día, mes, año (+año 2000), hora ,
minutos, y segundos (total 6 bytes)
o 8 bytes matricula.
• Respuesta (Coste):
o Euros (4 bytes)
o Céntimos (1 byte)
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
c)
CC
int main(){
crear_thread(&th1,control_puertas,“puerta1”);
crear_thread(&th2,control_puertas,“puerta2”));
crear_thread(&th3,control_puertas,“puerta3”);
crear_thread(&thN,control_maquinas,“maquina1”));
…
Esperar();
}
int control_ puertas (char *server){
control_puertas(char *server){
sd = conectar(server);
insertar_array_conexiones(&sd);
char tag = LIBRE; // = 1
enviar(sd,&tag, sizeof(char));
while(!cerrar){
recibir(sd, &datos, sizeof(datos));
tratar_datos(&datos, &res);
numero_coches++;
res.estado = LIBRE;
enviar(sd,&res, sizeof(res));
if(numero_coches == MAXIMO)
op = OCUPADO;
activar_envio_todos(op);
}
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
int control_ maquinas (char *server){
control_puertas(char *server){
sd = conectar(server);
char tag = LIBRE; // = 1
enviar(sd,&tag, sizeof(char));
while (){
recibir(sd,&len, sizeof(int));
}
close(sd);
}
Puertas
socket(…);
bind(…);
listen(…),
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
do{
recibir(sc, &estado, sizeof(char));
poner_estado(&estado); //LIBRE, COMPLETO, CERRADO
switch(estado){
case LIBRE:
break;
case COMPLETO:
break;
case CERRADO:
break;
}
}while(estado != CERRADO)
close(sc);
}
close (sd);
exit(0);
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
•
Interrupciones: pulsador , introducir_ticket, abrir_barrera
Mientras ejecuta el manejador el servidor puertas, se encuentra inhibido (el control lo tiene el
manejador de la interrupción).
void pulsador(){
if (estado == OCUPADO){
datos.op = ENTRAR;
datos.fecha = now();
datos.matricula = get_matricula();
enviar(sc , datos, sizeof(datos)); //sc variable global
recibir(sc , res, sizeof(res)); //sc variable global
}
}
void abrir_barrrera(){
datos.op = SALIR;
datos.fecha = now();
datos.matricula = get_matricula();
enviar(sc , datos, sizeof(datos)); //sc variable global
recibir(sc , res, sizeof(res)); //sc variable global
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Maquinas expendedoras
socket(…);
bind(…);
listen(…),
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
do{
recibir(sc, &estado, sizeof(char));
poner_estado(&estado); //LIBRE, COMPLETO, CERRADO
}while(estado != CERRADO)
close(sc);
}
close (sd);
exit(0);
•
Interrupciones: introducir_ticket
Mientras ejecuta el manejador de la maquina de tickets, se encuentra inhibido (el control lo
tiene el manejador de la interrupción).
void introducir_ticket (){
enviar(sc , info, sizeof(info));
recibir(sc , coste, sizeof(coste);
imprimir(coste);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Ejercicio 5. Un edificio, con 200 despachos, desea construir una aplicación que le permita
monitorizar la temperatura y humedad de cada uno de los despachos.
Sensor 1
Monitor
Sensor 200
Cada despacho consta de un sensor que toma cada segundo la temperatura y humedad del
despacho. Se dispone de un computador que hace de monitor y que permite visualizar los
datos de todos los despachos. El funcionamiento de la aplicación es el siguiente: cuando un
despacho se abre por las mañanas, el sensor situado en ese despacho envía un mensaje al
monitor indicándole que va a comenzar el proceso de monitorización. Cada segundo envía al
monitor los datos de temperatura y humedad del despacho. Cuando el despacho se cierra por
las tardes, el sensor envía un mensaje al monitor indicándole que deja de enviarle datos.
Suponiendo que se desea construir una aplicación cliente-servidor utilizando sockets, se pide:
a) Identifique en qué computador reside el cliente y en cuál el servidor.
b) ¿Qué tipo de sockets emplearía para esta aplicación? ¿Por qué?
c) Especifique el formato de los mensajes a intercambiar entre el cliente y el servidor y la
secuencia de mensajes a intercambiar entre ellos. Haga una estimación del tamaño
que ocuparían los mensajes.
De acuerdo al tipo de sockets empleado en el apartado b, indique qué llamadas de la
biblioteca de sockets utilizaría en el cliente y en el servidor.
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
a)
El servidor se encuentra en el monitor.
Los clientes se encuentran en los sensores.
b)
UDP. Ya que la pérdida de un dato no es relevante (lo es mas el rendimiento).
c)
struct datos{
char activar; // comunicación 1- activa, 0-desactivada
char despacho;
int temp;
int humedad;
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Sensor
void main(int argc, char *argv[])
{
struct sockaddr_in server_addr, client_addr;
struct hostent *hp;
if (argc != 2){
printf("Uso: cliente <direccion_servidor> \n");
exit(0);
}
s = socket(AF_INET, SOCK_DGRAM, 0);
hp = gethostbyname (argv[1]);
bzero((char *)&server_addr, sizeof(server_addr));
memcpy (&(server_addr.sin_addr), hp->h_addr, hp->h_length);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(7200);
bzero((char *)&client_addr, sizeof(client_addr));
client_addr.sin_family = AF_INET;
client_addr.sin_addr.s_addr
= INADDR_ANY;
client_addr.sin_port
= htons(0);
bind (s, (struct sockaddr *)&client_addr, sizeof(client_addr));
while(enviar){
t1 = time()
get_datos(&datos)
datos.activa = 1;
sendto(s, (char *)datos, sizeof(datos), 0,
(struct sockaddr *) &server_addr, sizeof(server_addr));
t2 = time()
sleep(1-(t2-t1));
}
datos.activa = 0;
sendto(s, (char *)&datos, sizeof(datos), 0,
(struct sockaddr *) &server_addr, sizeof(server_addr));
close(s);
}
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Monitor
#include <sys/types.h>
#include <sys/socket.h>
void main(void)
{
int s, res, clilen;
struct sockaddr_in server_addr, client_addr;
s = socket(AF_INET, SOCK_DGRAM, 0);
bzero((char *)&server_addr, sizeof(server_addr));
server_addr.sin_family
= AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port
= htons(7200);
bind(s, (struct sockaddr *)&server_addr, sizeof(server_addr));
clilen = sizeof(client_addr);
while (1)
{
recvfrom(s, (char *) &datos, izeof(datos), 0,
(struct sockaddr *)&client_addr, &clilen);
Imprimir(&datos);
}
} /* fin main */
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Ejercicio 6.
a) Los mensajes los genera la estación central. El que las procesa son las máquinas.
b) Si no fuera orientado a conexión, sería necesario usar un sistema de confirmación
de envío y recepción de los datos a través de UDP. Por ejemplo: si se realiza la
operación setdaytime() por parte de la estación central a una maquina, es
necesario realizar después la operación getdaytime() para comprobar que la
operación se ha realizado. En caso de la recepción de los datos, para evitar
bloqueos usar temporizadores (con la llamada select por ejemplo)
c)
struct time_st {
char date[25];
}
Servicio daytime
socket(…);
bind(…);//Puerto 13
listen(…),
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
obtenertiempo(&datatime);
enviar(sc, &datatime, sizeof(datatime));
close(sc);
}
close (sd);
exit(0);
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Servicio setdaytime
socket(…);
bind(…);//Puerto 14
listen(…),
while (1)
{
printf("esperando conexion\n");
sc = accept(sd, (struct sockaddr *)&client_addr,&size);
recibir(sc, &datatime, sizeof(datatime));
cambiartiempo(&datatime);
close(sc);
}
close (sd);
exit(0);
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
Estación central
sincronizado = 0;
while (!sincronizado){
fd = open(configuracion)
i = 0;
while(!feof(fd)){
server=leer(fd)
sd = conectar(server, 13);
read(sd, datetime[i], sizeof(datetime[i]));
close(sd);
i ++;
}
sincronizado = comprobar(datetime, 5s);
If (!sincronizado){
calcular_time(&datetime_new);
fd = open(configuracion)
while(!feof(fd)){
server=leer(fd)
sd = conectar(server, 14);
write(sd, datetime_new, sizeof(datetime_new));
close(sd);
i ++;
}
}
}
}
d) En principio no ya que la estación central realiza las operaciones de cliente y el
resto de servidor.
d) Se necesitaría un servicio que devolviese el nombre de la maquina. Esto es posible
usando comunicaciones a través de broadcast (usando un puerto prefijado). En
este caso, un servidor escucharía en un puerto determinado en cada una de las
máquinas, y la estación central enviaría un mensaje de broadcast a ese puerto.
Departamento de Informática
Grado en Ingeniería Informática
Sistemas Distribuidos
Ejercicios de sockets
NIA: ………………………………………………… GRUPO: …………………………………………………………
Nombre y apellidos: …………………………………………………………………………………………………..
if ((he=gethostbyname(“10.0.0.255”) == NULL) { //para usar broadcast
perror("gethostbyname");
exit(1);
}
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
struct sockaddr_in their_addr; // connector's address information
their_addr.sin_family = AF_INET; // host byte order
their_addr.sin_port = htons(SERVERPORT); // short, network byte order
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
int broadcast = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &broadcast, sizeof broadcast) == -1) {
perror("setsockopt (SO_BROADCAST)");
exit(1);
}
sendto(s, (char *)&data, sizeof(data), 0,
(struct sockaddr *) &server_addr, sizeof(server_addr));
Descargar