Universidad Simón Bolívar Departamento de Computación y Tecnología de la Información Curso de Redes I CI-4815 Trimestre Septiembre Diciembre 2013



Documentos relacionados
sockets Flujo (SOCK_STREAM) Comunicación bidireccional Confiable (entrega garantizada) Información ordenada en el destino Datagrama (SOCK_DGRAM)

Introducción a la programación con sockets en C

Problemas de Redes de Computadores. Conjunto de problemas 1

Examen Principios de Programación Febrero 2012

Sistemas Operativos Práctica 3

Sockets: funcionamiento y programación. Sockets tipo UNIX. MSc. Ivan A. Escobar

Ejercicio Sockets Suma Resta. Descripción

TELEPROCESO Y SISTEMAS DISTRIBUIDOS

SOLUCION EXAMEN junio 2006

Manual de operación Tausend Monitor

COPIAS DE SEGURIDAD AUTOMÁTICAS DE DIRECCIONES CALLEÇPAÑA

7. Manejo de Archivos en C.

Manual del Protocolo XML-RPC de Mensajería Negocios

ARQUITECTURA DE REDES Laboratorio

Práctica 1 Programación de Aplicaciones Distribuidas: Sockets UDP. Laboratorio de Comunicación de Datos ITT Telemática Septiembre 2011

Sistemas Operativos Práctica 4

5.2.- Configuración de un Servidor DHCP en Windows 2003 Server

El lenguaje C. #define MAX LINEA 1000 /* maximo tamanio de linea de entrada */

COMUNICACIÓN ENTRE PROCESOS SOCKETS

Introducción a las Redes de Computadoras. Obligatorio

Introducción de Sockets en C.

INTRODUCCIÓN AL TIPO COMPUESTO CADENA CONTENIDOS

Problemas de Redes de Computadores. Ingeniería Técnica en Informática de Gestión Conjunto de problemas 1

Análisis y diseño del sistema CAPÍTULO 3

OBJETIVOS. Explicar el manejo de archivos de texto. Explicar el manejo de archivos binarios. Desarrollar programas que usen archivos.

Sockets (TCP) Tema 2.- Nivel de aplicación en Internet

CAPÍTULO HTML Y DHCP DE H0/H2-ECOM100 CONFIGURACIÓN. En este capítulo...

Punteros. Definición Un puntero es un dato que contiene una dirección de memoria.

TEMA 8: ESTRUCTURAS DE DATOS COMPLEJAS 1 VECTORES ESTÁTICOS 2 2 CADENAS O VECTORES DE CARACTERES 6 3 PASO DE CADENAS Y ARRAYS A FUNCIONES 8

Tutorial: Cómo realizar tu primer programa en C++ En el Sistema Operativo Windows

Instituto Politécnico Nacional

Objetivos de la práctica: - Practicar uso de ficheros: abrir, cerrar y tratamiento de información contenida en el fichero.

Características de un lenguaje ideal para robótica

Introduccion al Lenguaje C. Omar Andrés Zapata Mesa Grupo de Fenomenología de Interacciones Fundamentales, (Gfif) Universidad de Antioquia

MANUAL DE USUARIO DE CUENTAS DE CORREO

INSTALACIÓN Y CONFIGURACION DNS WINDOWS SERVER 2003

Organización de Computadoras

Preliminares. Tipos de variables y Expresiones

PRÁCTICA 4 PASO DE MENSAJES

ALGUNAS AYUDAS PARA EL ACCESO AL AULA DIGITAL Contenido

HOW TO SOBRE FIREWALL

Guías _SGO. Gestione administradores, usuarios y grupos de su empresa. Sistema de Gestión Online

Comisión Nacional de Bancos y Seguros

Memoria compartida y semáforos r/w. La página del manual que podría servir para describir estas funciones es la siguiente:

GUIA COMPLEMENTARIA PARA EL USUARIO DE AUTOAUDIT. Versión N 02 Fecha: 2011-Febrero Apartado: Archivos Anexos ARCHIVOS ANEXOS

SISTEMA DE APARTADO DE SALAS PARA EVENTOS

Paso de Borland Turbo C (bajo DOS) a Anjuta (Linux) 1.

Uso del Shield Ethernet con Arduino

Conexión a red LAN con servidor DHCP

Esquema de un programa en C: bloques básicos

Modulo 1 El lenguaje Java

En caso de que el cliente nunca haya obtenido una concesión de licencia de un servidor DHCP:

MANUAL DE LA APLICACIÓN HELP DESK

Dirección Alumnos. Av. Benjamín Aráoz C.P Tucumán - Argentina Tels.: 0054 (0381) Fax: Internet:

Mecanismos IPC: sockets

Cómo ingresar a la Sucursal Electrónica?

Guía Notas Parciales. Intermedio

Pantalla ENW URL LOGIN

SMS Plus Qué es? Cómo funciona?

OPERACIONES BASICAS. 1. Menú. 2. Barra de Herramientas. 3. Área de trabajo. 3.1 Operaciones Básicas. Revisión 3.0

Tema 4 El paradigma cliente-servidor

Capitulo 5. Implementación del sistema MDM

Arranque de la aplicación

UNIVERSIDAD DON BOSCO FACULTAD DE ESTUDIOS TECNOLÓGICOS COORDINACION DE COMPUTACIÓN PROYECTO DE CÁTEDRA. MATERIA: Introducción a la Programación

Introducción a la programación orientada a objetos

Estructuras y funciones de programación de sockets.

1. Ejemplo de clase : La clase Cuenta 2. Uso de la clase Cuenta. 3. Métodos y objetos receptores de mensajes (Importante)

Sociedad de Seguros de Vida del Magisterio Nacional. Sistema de Pignoraciones Web. Manual de Usuario. Marzo, 2012.

Tema: Sobrecarga de Operadores.

CONFIGURACION AVANZADA DE MOZILLA THUNDERBIRD

WINDOWS : SERVIDOR DHCP

Descripción del Problema Sistema de Reservaciones de Vuelos

Análisis Experimental de la Transmisión de Datos

Cómo crear su perfil de WOK?

SOR -::- Prácticas -::- Curso 05/06. RCP es un estándar desarrollado por Sun Microsystems y usado por muchos distribuidores de sistemas UNIX.

Acronis License Server. Guía del usuario

SIIGO PYME PLUS. Proceso de Recuperación. Cartilla I

Crear un servidor DHCP

Configuracion Escritorio Remoto Windows 2003

SCHOOL OF HACKING 2015 RETO BUFFER OVERFLOW

El lenguaje de Programación C. Fernando J. Pereda

Administración de la producción. Sesión 10: Gestor de Base de Datos (Access)

Listas, Pilas, Colas y Punteros. Semana 3

INSTITUTO TECNOLÓGICO DE COLIMA LIC. EN INFORMÁTICA

Gestión de Permisos. Bizagi Suite. Copyright 2014 Bizagi

MANUAL DE USUARIO CONSEJO PUEBLA DE LECTURA A.C. Instituto Nacional de Astrofísica, Óptica y Electrónica. 01/Octubre/2009

LABORATORIO 2. La biblioteca a nivel de usuario semso (semáforos Sistemas Operativos) brinda las siguientes primitivas:

CheckOUT HELP DESK. Una vez en sesión, UD. Podrá registrar problemas, consultas y hacer un seguimiento de los problemas que UD. ha ingresado.

Práctica GESTIÓN Y UTILIZACIÓN DE REDES LOCALES. Curso 2001/2002. TCP/IP: protocolo TCP

Abelardo Pardo. Iria Estévez Ayres. Damaris Fuentes Lorenzo. Pablo Basanta Val. Pedro J. Muñoz Merino. Hugo A. Parada.

SISTEMA DE ATENCIÓN y GESTIÓN MANUAL DEL USUARIO. SAyGeS v2.0

Árboles. Cursos Propedéuticos Dr. René Cumplido M. en C. Luis Rodríguez Flores

Esta extensión está obsoleta a partir de PHP 5.5.0, y será eliminada en el futuro

Aplicaciones Cliente/Servidor en Gambas Prof: Mileti, P.

Manual EDT DISEÑO EDT - CREAR EVENTO DE DIVULGACIÓN TECNOLÓGICA

Manual de uso de la plataforma para monitores. CENTRO DE APOYO TECNOLÓGICO A EMPRENDEDORES -bilib

Sistema Tecnológico de Apoyo a la Regulación

Prof. Dr. Paul Bustamante

Redes de área local: Aplicaciones y servicios WINDOWS

Control de accesos autónomo por huella dactilar

Transcripción:

Universidad Simón Bolívar Departamento de Computación y Tecnología de la Información Curso de Redes I CI-4815 Trimestre Septiembre Diciembre 2013 Proyecto I Autores: Lairon Acosta. Carnet: 09-10927 Jueves 28 de Noviembre de 2013

Explicación del Diagrama de Secuencia 1. El programa cchat1 envia comando men Hola al servidor, este lo recibe y lo envia a todos los usuarios conectados a las mismas salas de chat que cchat1, en este caso a cchat2 que recibe el mensaje. 2. El programa cchat1 envia comando usu al servidor, este lo recibe y procesa la petición, busca todos los usuarios conectados y le envia respuesta al programa cchat1. 3. El programa cchat1 envia comando sal al servidor, este lo recibe y procesa la petición, busca todas las salas disponibles y le envia respuesta al programa cchat1. 4. El programa cchat1 envia comando crea nueva al servidor, este lo recibe y procesa la petición, crea una sala de nombre 'nueva' y le envia respuesta al programa cchat1 de sala creada exitosamente. 5. El programa cchat1 envia comando des al servidor, este lo recibe y procesa la petición, dessuscribe al cliente cchat1 de todas las salas a la que esta conectado y le envia respuesta al programa cchat1 de operación exitosa. 6. El programa cchat1 envia comando sus nueva al servidor, este lo recibe y procesa la petición, suscribe al cliente cchat1 a la sala de nombre 'nueva' y le envia respuesta al programa cchat1 de suscricción exitosa. 7. El programa cchat1 envia comando men chao al servidor, este lo recibe y lo envia a todos los usuarios conectados a las mismas salas de chat que cchat1, en este caso a cchat2 que recibe el mensaje. 1- Verificación de comandos: Explicación de los Aspectos del Proyecto Para la verificación de los comandos se utilizó Expresiones Regulares. Estas permitieron verificar tanto patrones de comando como tipo de cada parámetro de forma más fácil. Por lo tanto, las expresiones regulares usadas para cada comando válido se muestran a continuación: expmensaje[] = " *men *[a-za-z0-9.,-?'!\"#$%&/()@+-/*\\][a-za-z 0-9.,-?'!\"#$%&/() @+-/*\\]* *$"; expcrearsala[] = " *cre *[a-za-z0-9][a-za-z0-9]* *$"; expsuscribesala[] = " *sus *[a-za-z0-9][a-za-z0-9]* *$"; expeliminasala[] = " *eli *[a-za-z0-9][a-za-z0-9]* *$"; expsalas[] = " *sal *$";

expusuarios[] = " *usu *$"; expdessuscribir[] = " *des *$"; expfuerachat[] = " *fue *$"; 2- Estructuras de datos: Se crearon especificamente dos estructuras de datos, la primera para almacenar la información de cada usuario conectado al servidor y la segunda para administrar las salas disponibles del servidor. Primera estructura: Id socket de usuario Nombre de usuario Estado de usuario: Conectado Desconectado Salas de usuario Segunda estructura: Nombre de sala Estado de sala: Activa Desactiva 3- Cliente/Servidor multihilo: Se usó la nocion de Cliente/Servidor multihilo. De tal manera, para cada cliente se crearon dos hilos, uno para que recibiera las respuestas del servidor y otro para enviar peticiones al servidor. De la misma forma, para el servidor se creó un hilo por cada cliente aceptado para recibir peticiones, este hilo ejecuta una funcion para gestionar las distintas peticiones de los clientes. 4- Funciones de los comandos(diseño del programador): Comando 'men (texto)': este comando envia el (texto) a todos los usuarios conectados a la misma sala del enviador. No se envia el (texto) así mismo por cuestiones de acuerdos, debido a que en el enunciado no tiene ésta restricción explícita. Comando 'sus (Sala)': este comando suscribe al usuario que lo invoca a una sala que este disponible, es decir, que este creada. Si la sala no existe le envía un aviso al usuario. Comando 'cre (Sala)': este comando hace que el usuario que lo invoca cree una sala que no haya sido creada y simultaneamente lo suscribe a ella. Si la sala ya fué creada le envía un aviso al usuario. Comando 'eli (Sala)': este comando hace que el usuario que lo invoca elimine una sala

cualquiera que este creada. Simultaneamente, des-sucribe a todos los usuarios que esten suscritos a ella y les envía un mensaje informando que la sala ha sido eliminada. Si la sala no existe le envía un aviso al usuario. Comando 'sal ': Este comando le muestra por pantalla al usuario que lo invoca una lista de las salas disponibles del servidor. Comando 'usu ': Este comando le muestra por pantalla al usuario que lo invoca una lista de los usuarios suscritos al servidor, incluyéndolo a él mismo. Comando 'fue ': Este comando le permite al usuario que lo invoca terminar el programa de introducción de comandos y al mismo tiempo la terminación del programa cchat. Además, le envía un aviso al usuario de que ha terminado su ejecución de comandos y programa cchat. 5- Restricciones de parámetros de las llamadas cchat y schat: Para la llamada del programa schat, tenemos que los parámetros de entrada podran venir en cualquier orden. Destacando que el parámetro de la opcion '-s' puede existir o no. Llamada: schat [-p <puerto>] [-s <sala>] Para la llamada del programa cchat, los parámetros podrán venir en cualquier orden igualmente, pero los parámetros de cada opción son obligatorios. Destacando con esto, que debe existir archivo de entrada obligatoriamente para la opción '-a'. Esto debido acuerdo tomado por el programador. Llamada: cchat [-h <host>] [-p <puerto>] [-n <nombre>][-a <archivo>] 6- Entradas inválidas en llamadas y comportamiento a tomar: Se presentan una serie de entradas inválidas o errores y sus respectivos manejos: Error abriendo socket: El programa termina su ejecución y envía mensaje de error abriendo socket. Error en el puerto: El programa termina su ejecución y envía mensaje de error en el puerto. Error en el host: El programa termina su ejecución y envía mensaje de error en el host. Error realizando 'bind' socket: El programa termina su ejecución y envía mensaje de error en el bind. Error realizando 'listen' socket: El programa termina su ejecución y envía mensaje de error en el listen. Error realizando 'connect' socket: El programa termina su ejecución y envía mensaje de error en el connect.

Número inválido de argumentos: El programa termina su ejecución y envía mensaje de error número inválido de argumentos. Error de opción inválida: El programa termina su ejecución y envía mensaje de error de opción no corresponde o no es válida. Error de opción en posición inválida: El programa termina su ejecución y envía mensaje de error de opción en posición inválida. Error en compilar expresión regular(no aparecerá): El programa termina su ejecución y envía mensaje de error de expresión regular no compilada. Error abriendo archivo: El programa termina su ejecución y envía mensaje de error abriendo archivo. Error al crear hilo: El programa termina su ejecución y envía mensaje de error al crear hilo en el cliente o servidor. 7- Estado del proyecto: El proyecto tiene 100% de funcionalidad y está 100% documentado.

/* Proyecto 1: Redes ci4815 Programa: Cliente.c Realizado por: Lairon Acosta Version: 2.7 ------------------------------ Includes del sistema #include <stdio.h> #include <string.h> #include <stdlib.h> #include <Cola.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <SocketCliente.h> #include <pthread.h> #include <sys/syscall.h> #include <sys/resource.h> #include <errno.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <fcntl.h> #include <sys/time.h> /*funcion: funcion principal que realiza las acciones de un cliente argc: cantidad de argumentos argv: argumentos de la llamada del cliente main ( int argc, char *argv[] ) { //Declaracion de variables Cola cola = NULL; char host[100]; char puerto[100]; char nombre[100]; char archivo[100]; char Cadena[100]; int fd_socket; int rc1, rc2; long id_hilo; pthread_t threads[2]; Parametros *comandos; // Comando de entrada: cchat [-h <host>] [-p <puerto>] [-n <nombre>][-a <archivo>]

//si hay 9 argumentos, proceso argumentos if ( argc == 9 ) { /* llamo a funcion que identificara la correspondencia de los argumentos del programa principal procesarargumentoscliente(argc, argv, &cola); strcpy(host, dameprimero(&cola)); //Obtengo host strcpy(puerto, dameprimero(&cola)); //Obtengo puerto strcpy(nombre, dameprimero(&cola)); //Obtengo nombre strcpy(archivo, dameprimero(&cola)); //Obtengo archivo cola=null; //destruccion de la cola free(cola); //sino envio error else { printf ("Programa %s.c: Error: numero invalido de argumentos.\n", argv[0]); exit(-1); // Inicia configuracion de conexion de Sockets //Se abre la conexion con el cliente fd_socket = ConexionInetCliente(host,puerto); /* Allocate memory for pthread_create() arguments comandos = calloc(1,sizeof(struct parametros)); //si hay memoria if (comandos == NULL) { printf("error: no hay memoria para almacenar argumentos"); exit(-1); //almaceno numero de socket y nombre de archivo comandos[0].idsocketusuario = fd_socket; strcpy(comandos[0].texto,archivo); if ( fd_socket == -1) { printf("error DE CONEXION INET\n"); exit(-1); else { //socket para enviar el nombre del usuario send( fd_socket, nombre, strlen(nombre)+1, 0); //crea hilo para enviar mensajes if ( ( rc1 = pthread_create( &threads[0], NULL, enviarmensaje, &comandos[0])) ) {

printf("error al crear hilo para recibir mensaje\n"); close(fd_socket); exit(-1); //crea hilo para recibir mensajes if ( ( rc2 = pthread_create( &threads[1], NULL, recibirmensaje, (void *)(intptr_t) fd_socket)) ) { printf("error al crear hilo para enviar mensaje\n"); close(fd_socket); exit(-1); //envio comandos del archivo sino hubo errores de archivo if(!enviarcomandos(fd_socket, archivo)){ printf("error abriendo archivo y no envio comandos del archivo\n"); exit(-1); //espero por los hilos creados pthread_join( threads[0], NULL); pthread_join( threads[1], NULL); //cierro socket close(fd_socket);

/* Proyecto 1: Redes ci4815 Programa: SocketCliente.c Realizado por: Lairon Acosta Version: 1.3 ----------------------------- Includes del sistema #include <stdio.h> #include <string.h> #include <stdlib.h> #include <Cola.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/syscall.h> #include <sys/resource.h> #include <errno.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <fcntl.h> #include <sys/time.h> #include <regex.h> #include <SocketCliente.h> /*******Implementaciones de metodos******* /*funcion: realiza conexion de sockets con el servidor arg1: direccion ip o nombre de maquina del cliente arg2: puerto donde recibira la conexion return: descriptor de conexion int ConexionInetCliente ( char *host, char *puerto) { //Declaracion de variables int fd_socket; struct sockaddr_in address; struct in_addr inaddr; struct hostent *host_cliente; // Inicia configuracion de conexion de Sockets // Si el argumento se puede convertir en una direccion IP lo hace, de lo contrario busca en DNS if ( inet_aton(host,&inaddr) ) { host_cliente = gethostbyaddr((char *) &inaddr, sizeof(inaddr), AF_INET); //printf("host by ip\n"); else {

host_cliente = gethostbyname(host); //printf("host by name\n"); //verifica si se obtuvo error en la obtencion del hostent if (!host_cliente) { printf("error en el host\n"); return -1; // //Llenamos la estructura para TCP/IP address.sin_family = AF_INET; //DIR PROTOCOLO address.sin_addr.s_addr = ((struct in_addr *)(host_cliente->h_addr))->s_addr; //dir HOST //verifica si se obtuvo error en el puerto if (!(address.sin_port = htons(atoi(puerto))) ) { //dir PUERTO printf("error en el puerto\n"); return -1; // //Abrimos el socket if(( fd_socket = socket (PF_INET, SOCK_STREAM, 0)) < 0) { printf("error abriendo el socket\n"); return -1; // //Conectamos el socket if ( (connect(fd_socket, (struct sockaddr *) &address, sizeof(address))) == -1 ) { printf("error en funcion -connect- del socket: \n"); perror("connect"); return -1; // return fd_socket; /*funcion: envia mensajes al servidor arg1: descriptor de conexion void *enviarmensaje ( void * id_hilo ) { char buffer[300]; int id; struct parametros *comandos = (struct parametros *) id_hilo;

id = comandos->idsocketusuario; while(1) { fgets(buffer, 300, stdin); send( id, buffer, strlen(buffer)+1, 0); /*funcion: recibe mensajes del servidor arg1: descriptor de conexion void *recibirmensaje ( void *id_hilo ) { char buffer[300]; int id; id = (int)(intptr_t)id_hilo; while(1) { recv( id, buffer, 300, 0); if( strcmp(buffer,"fue")==0){ printf("termino la ejecucion de comandos y el programa cchat satisfactoriamente.\n\n"); exit(-1); printf("%s\n",buffer); fflush(stdout); /*funcion: envia comandos de un archivo al servidor arg1: id de usuario a que pertenece el archivo arg2: nombre del archivo int: 1 si envio comandos exitosamente, 0 sino. int enviarcomandos(int id, char *archivo) { FILE *ficheroentrada; char buffere[200]; int j=0; //abro archivo de entrada ficheroentrada = fopen( archivo, "r" );

if (!ficheroentrada) { //IMPRIME ERROR //printf("mensaje: **ERROR ABRIENDO ARCHIVO DE ENTRADA\n"); return 0; else { //Extrae cada palabra del archivo while (feof(ficheroentrada) == 0) { fgets(buffere,200,ficheroentrada); if (feof(ficheroentrada) == 0) { printf("%s",buffere); send( id, buffere, strlen(buffere)+1, 0); strcpy(buffere, ""); sleep(1); fclose(ficheroentrada); return 1; //CIERRA EL archivo de entrada /*funcion: procesa los argumentos de la llamada Cliente arg1: cantidad de argumentos arg2: lista de argumentos arg3: cola que saldra modificada void procesarargumentoscliente(int numeroarg, char *argv[], Cola *cola) { char retorno[5][50]; // Comando de entrada: cchat [-h <host>] [-p <puerto>] [-n <nombre>][-a <archivo>] if( strcmp(argv[1],"-h") == 0 ) { //copia el host en la posicion 0 del arreglo retorno strcpy(retorno[0],argv[2]); if( strcmp(argv[3],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[4]); if( strcmp(argv[5],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno

strcpy(retorno[2],argv[6]); if( strcmp(argv[7],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[8]); printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[7],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[8]); if( strcmp(argv[5],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[6]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n no corresponde\n"); else if( strcmp(argv[5],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[6]); if( strcmp(argv[3],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[4]); if( strcmp(argv[7],"-a") == 0 ) {

else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[8]); printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[7],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[8]); if( strcmp(argv[3],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[4]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[7],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[8]); if( strcmp(argv[3],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[4]); if( strcmp(argv[5],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[6]);

printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[5],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[6]); if( strcmp(argv[3],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[4]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else { printf ("Error: argumento -p en pos invalida\n"); else if ( strcmp(argv[3],"-h") == 0 ) { //copia el host en la posicion 1 del arreglo retorno strcpy(retorno[0],argv[4]); if( strcmp(argv[1],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[2]); if( strcmp(argv[5],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[6]); if( strcmp(argv[7],"-a") == 0 ) {

else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[8]); printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[7],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[8]); if( strcmp(argv[5],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[6]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[5],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[6]); if( strcmp(argv[1],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[2]); if( strcmp(argv[7],"-a") == 0 ) { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[8]);

else { printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[7],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[8]); if( strcmp(argv[1],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[2]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[7],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[8]); if( strcmp(argv[1],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[2]); if( strcmp(argv[5],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[6]); printf ("Error: argumento -a en pos invalida\n");

else if( strcmp(argv[5],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[6]); if( strcmp(argv[1],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[2]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else { printf ("Error: argumento -p en pos invalida\n"); else if ( strcmp(argv[5],"-h") == 0 ) { //copia el host en la posicion 1 del arreglo retorno strcpy(retorno[0],argv[6]); if( strcmp(argv[1],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[2]); if( strcmp(argv[3],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[4]); if( strcmp(argv[7],"-a") == 0 ) { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[8]);

else { printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[7],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[8]); if( strcmp(argv[3],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[4]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[3],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[4]); if( strcmp(argv[1],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[2]); if( strcmp(argv[7],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[8]); printf ("Error: argumento -a en pos invalida\n");

else if( strcmp(argv[7],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[8]); if( strcmp(argv[1],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[2]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[7],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[8]); if( strcmp(argv[1],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[2]); if( strcmp(argv[3],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[4]); printf ("Error: argumento -a en pos invalida\n");

else if( strcmp(argv[3],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[4]); if( strcmp(argv[1],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[2]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else { printf ("Error: argumento -p en pos invalida\n"); else if ( strcmp(argv[7],"-h") == 0 ) { //copia el host en la posicion 1 del arreglo retorno strcpy(retorno[0],argv[8]); if( strcmp(argv[1],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[2]); if( strcmp(argv[3],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[4]); if( strcmp(argv[5],"-a") == 0 ) { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[6]);

else { printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[5],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[6]); if( strcmp(argv[3],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[4]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[3],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[4]); if( strcmp(argv[1],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[2]); if( strcmp(argv[5],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[6]); printf ("Error: argumento -a en pos invalida\n");

else if( strcmp(argv[5],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[6]); if( strcmp(argv[1],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[2]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else if( strcmp(argv[5],"-p") == 0 ) { //copia el puerto en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[6]); if( strcmp(argv[1],"-n") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[2]); if( strcmp(argv[3],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[4]); printf ("Error: argumento -a en pos invalida\n"); else if( strcmp(argv[3],"-n") == 0 ) {

//copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[2],argv[4]); if( strcmp(argv[1],"-a") == 0 ) { else { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[3],argv[2]); printf ("Error: argumento -a en pos invalida\n"); else { printf ("Error: argumento -n en pos invalida\n"); else { printf ("Error: argumento -p en pos invalida\n"); else { printf ("Error: argumento -h en pos invalida\n"); InsertarPalabra (cola, retorno[0]); InsertarPalabra (cola, retorno[1]); InsertarPalabra (cola, retorno[2]); InsertarPalabra (cola, retorno[3]);

/* Proyecto 1: Redes ci4815 Programa: SocketCliente.h Realizado por: Lairon Acosta Version: 1.5 /*Definiciones de tipos y estructuras de datos /* Estructura para manejar los comandos del archivo var1: contenido del archivo var2: id de usuario al que le pertenece el archivo typedef struct parametros { char texto[300]; int idsocketusuario; Parametros; /*******Definiciones de metodos******* /*funcion: realiza conexion de sockets con el servidor arg1: direccion ip o nombre de maquina del cliente arg2: puerto donde recibira la conexion return: descriptor de conexion int ConexionInet (char *host, char *puerto); /*funcion: envia mensajes al servidor arg1: descriptor de conexion void *enviarmensaje ( void *id_hilo ); /*funcion: recibe mensajes del servidor arg1: descriptor de conexion void *recibirmensaje ( void *id_hilo ); /*funcion: procesa los argumentos de la llamada Cliente arg1: cantidad de argumentos arg2: lista de argumentos arg3: cola que saldra modificada void procesarargumentoscliente(int numeroarg, char *argv[], Cola *cola); /*funcion: envia comandos de un archivo al servidor arg1: id de usuario a que pertenece el archivo arg2: nombre del archivo int: 1 si envio comandos exitosamente, 0 sino. int enviarcomandos(int id, char *archivo);

/* Proyecto 1: Redes ci4815 Programa: Servidor.c Realizado por: Lairon Acosta Version: 4.8 ------------------------------ Includes del sistema #include <stdio.h> #include <string.h> #include <stdlib.h> #include <Cola.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <pthread.h> #include <sys/syscall.h> #include <sys/resource.h> #include <SocketServidor.h> /*funcion: administra los comandos enviados por el cliente arg1: descriptor de conexion void *funcionesusuario( void *p); //VARIABLES GLOBALES datausuario usuario[100]; salausuario sistemasala[150]; int clientes = 0; pthread_mutex_t mutex; /*funcion: funcion principal que realiza las acciones de un servidor argc: cantidad de argumentos argv: argumentos de la llamada del cliente main(int argc, char *argv[]) { //Declaracion de variables Cola cola = NULL; char puerto[100]; char sala[100]; char Cadena[100]; char nombreuser[147]; int fd_socket, fd_socketcliente, i, rc; int id; pthread_t threads[100];

//Inicializacion de variales pthread_mutex_init (&mutex, NULL); //inicializa el mutex //bloquear area compartida, mutex pthread_mutex_lock (&mutex); for( i=0 ; i<100 ; i++ ) { strcpy( usuario[i].nombreusuario, " "); // Comando de entrada: schat [-p <puerto>] [-s <sala>] if ( argc == 5 ) { /* llamo a funcion que identificara la correspondencia de los argumentos del programa principal procesarargumentosservidor(argc, argv, &cola); strcpy(puerto, dameprimero(&cola)); //Obtengo host strcpy(sala, dameprimero(&cola)); //Obtengo puerto cola=null; //destruccion de la cola free(cola); else if( argc == 4 ) { /* llamo a funcion que identificara la correspondencia de los argumentos del programa principal procesarargumentosservidor2(argc, argv, &cola); strcpy(puerto, dameprimero(&cola)); //Obtengo host strcpy(sala, dameprimero(&cola)); //Obtengo puerto cola=null; //destruccion de la cola free(cola); else { printf ("Programa %s.c: Error: numero invalido de argumentos.\n", argv[0]); exit(-1); //incorporo el numero de salas strcpy(sistemasala[0].nombresala, "tamaño"); sistemasala[0].numerosala = 1; //incorporo la sala por defecto en el arreglo de salas

strcpy(sistemasala[1].nombresala, sala); sistemasala[1].numerosala = 1; //Almaceno al servidor como usuario por defecto //Almaceno la sala por defecto id = clientes; usuario[id].idsocket = 0; strcpy(usuario[id].nombreusuario, "Servidor"); usuario[id].conectadousuario = 1; //strcpy(usuario[id].nombresala, sala); InsertarPalabra(&usuario[id].salas, sala); //aumento clientes para comenzar a recibir clientes++; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); // Inicia configuracion de conexion de Sockets //Se abre la conexion con el servidor fd_socket = ConexionInetServidor(puerto); if ( fd_socket == -1 ) { printf("error DE CONEXION INET\n"); exit(-1); //Me quedo esperando peticiones de usuarios para aceptar for (;;) { //Servidor espera solicitudes del cliente fd_socketcliente = AceptaConexionInetCliente(fd_socket); if ( fd_socketcliente == -1 ) { printf ("Error al aceptar solicitudes de clientes\n"); exit (-1); else { //bloquear area compartida, mutex pthread_mutex_lock (&mutex); id = clientes; //le asigna id a usuario nuevo //almaceno fd_socket de usuario usuario[id].idsocket = fd_socketcliente; //si la sala por defecto fue eliminada if(sistemasala[1].numerosala == -1) { //marco usuario como desconectado

usuario[id].conectadousuario = 0; usuario[id].salas = NULL; else { //marco usuario como conectado usuario[id].conectadousuario = 1; //almaceno nombre sala de usuario InsertarPalabra(&usuario[id].salas, sala); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //para recibir nombre de usuario recv(usuario[id].idsocket, nombreuser, 100, 0); //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //almaceno nombre de usuario strcpy(usuario[id].nombreusuario,nombreuser); strcpy(nombreuser, ""); clientes++; //aumento el numero de clientes //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); (intptr_t)id)) ) { //creo hilo por cada cliente aceptado y proceso su peticion if ( (rc = pthread_create( &threads[id], NULL, funcionesusuario, (void *) printf("error al crear el hilo de funciones de usuarios\n"); close(id); exit(-1); //Espero por los hilos de clientes que se estan procesando pthread_join( threads[id], NULL); //Se cierran los sockets close (fd_socketcliente); //cliente close (fd_socket); //servidor void *funcionesusuario( void *p) { int ide; ide = (int)(intptr_t)p;

char buffer[300]; char funcion[147]; char mensaje[300]; char nombreauxiliar[147]; char nombreauxiliar2[147]; int i, longitud, destino,j=0,e=0,tam=0,numsalas=0; //expresiones regulares para los formatos de comandos y parametros char expmensaje[] = " *men *[a-za-z0-9.,-?'!\"#$%&/()@+-/*\\][a-za-z 0-9.,-?'!\"#$%&/ ()@+-/*\\]* *$"; char expcrearsala[] = " *cre *[a-za-z0-9][a-za-z0-9]* *$"; char expsuscribesala[] = " *sus *[a-za-z0-9][a-za-z0-9]* *$"; char expeliminasala[] = " *eli *[a-za-z0-9][a-za-z0-9]* *$"; char expsalas[] = " *sal *$"; char expusuarios[] = " *usu *$"; char expdessuscribir[] = " *des *$"; char expfuerachat[] = " *fue *$"; //me quedo esperando comandos por cliente cualquiera while(1) { j=0; e=0; tam=0; numsalas=0; recv(usuario[ide].idsocket, buffer, 300, 0); longitud = strlen(buffer); buffer[longitud-1]='\0'; //vacio buffers strcpy( nombreauxiliar2, ""); //vacio buffers strcpy( nombreauxiliar, ""); //guardo el nombre del usuario en otra variable strcpy( nombreauxiliar2, usuario[ide].nombreusuario); printf ("%s: %s\n",nombreauxiliar2, buffer); /*****************************COMANDOS******************************** //envio mensaje a todos los usuarios conectados a la misma //sala del servidor if( formatovalido( expmensaje, buffer) == 1 ) { //bloquear area compartida, mutex pthread_mutex_lock (&mutex);

//obtengo nombre de comando y parametro strcpy(funcion, primerapalabra(buffer, longitud)); //guardo el nombre del usuario en otra variable strcpy( nombreauxiliar, usuario[ide].nombreusuario); //concateno para mejorar el formato del mensaje a enviar strcat( nombreauxiliar, " dice: "); strcat( nombreauxiliar, buffer); strcat( mensaje, nombreauxiliar); //envio mensaje para cada usuario for(i = 1; i < clientes; i++) { //que sea distinto a mi mismo y que este conectado if( i!= ide && usuario[i].conectadousuario == 1) { //numero de salas a la que esta suscrito el //usuario ide. tam = tamano(&usuario[ide].salas); //cada elemento de la cola de Salas de usuario for(j=1 ; j <= tam; j++) { //si otro usuario pertenece a mis salas if( pertenece( &usuario[i].salas, elemento(&usuario[ide ].salas,j) ) ) { j = tam+1; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[i].idsocket, mensaje, strlen(mensaje) +1, 0); //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); strcpy( nombreauxiliar, ""); //la peticion es mostrar las salas que posee el servidor else if( formatovalido( expsalas, buffer) == 1 ) {

//bloquear area compartida, mutex pthread_mutex_lock (&mutex); //obtengo el numero de salas en el servidor numsalas = sistemasala[0].numerosala; //concateno para mejorar formato de mensaje respuesta strcat( mensaje, "Salas del servidor: \n"); //almaceno las salas activas actuales for(i = 1; i <= numsalas; i++) { //si la sala no fue eliminada if(sistemasala[i].numerosala!= -1) { //concateno para mejorar formato de mensaje respuesta strcat( mensaje, sistemasala[i].nombresala); strcat( mensaje, "\n"); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); strcpy( mensaje, ""); strcpy( buffer, ""); //La peticion del usuario es crear una sala en el servidor. else if( formatovalido( expcrearsala, buffer) == 1 ) { //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //obtengo nombre de comando y parametro strcpy(funcion, primerapalabra(buffer, longitud)); //obtengo el numero de salas en el servidor numsalas = sistemasala[0].numerosala; //se verifica si la sala ya existe for(i = 1; i <= numsalas ; i++) { //si encontro la sala, cambia la bandera 'j' a true if(strcmp(sistemasala[i].nombresala, buffer) == 0 && sistemasala[i ].numerosala!= -1) { //cambio bandera a true j = 1; //termino ciclo i = numsalas + 1; //sino existe la sala proceso peticion accion

if ( j == 0 ) { //concateno para mejorar formato de mensaje respuesta strcat( mensaje, "Se ha creado la sala "); strcat( mensaje, "\""); strcat( mensaje, buffer); strcat( mensaje, "\""); strcat( mensaje, " satisfactoriamente.\n"); //aumento el numero de salas sistemasala[0].numerosala++; //obtengo el numero de salas en el servidor numsalas = sistemasala[0].numerosala; //guardo el numerosala de la nueva sala sistemasala[numsalas].numerosala = numsalas; //guardo el nombre de la nueva sala strcpy( sistemasala[numsalas].nombresala, buffer ); //agrego sala a cola de salas de usuario InsertarPalabra(&usuario[ide].salas,buffer); //coloco al usuario como conectado a la sala nueva usuario[ide].conectadousuario = 1; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //si la sala ya existe, envio respuesta else { //concateno para mejorar formato de mensaje de respuesta strcat( mensaje, "La sala ya existe. \n"); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); //la peticion es mostrar una lista todos los usuarios conectados else if ( formatovalido( expusuarios, buffer) == 1 ) { //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //concateno para mejorar el formato de mensaje a enviar

strcat( mensaje, "Usuarios conectados: \n"); //para cada cliente verifico for(i = 1; i < clientes; i++) { //si el usuario esta conectado if( usuario[i].conectadousuario == 1 ) { //lo concateno con usuarios conectados strcat( mensaje, usuario[i].nombreusuario); strcat( mensaje, "\n"); j=1; //hay usuarios conectados if (j==1) { //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); else { strcpy( mensaje, ""); //concateno para mejorar el formato de mensaje a enviarcomandos strcat( mensaje, "No hay Usuarios conectados\n"); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); //el usuario se suscribe a una sala else if( formatovalido( expsuscribesala, buffer) == 1 ) { //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //obtengo nombre de comando y parametro strcpy(funcion, primerapalabra(buffer, longitud)); //obtengo el numero de salas en el servidor numsalas = sistemasala[0].numerosala; //se verifica si la sala ya existe for(i = 1; i <= numsalas ; i++) { //si encontro la sala, cambia la bandera 'j' a true if(strcmp(sistemasala[i].nombresala, buffer) == 0 && sistemasala[i ].numerosala!= -1) {

//cambio bandera a true j = 1; //termino ciclo i = numsalas + 1; //si existe la sala, proceso peticion accion if ( j == 1 ) { if( pertenece( &usuario[ide].salas, buffer ) ) { //concateno para mejorar formato de mensaje de respuesta strcat( mensaje, "Usted ya esta suscrito a esta sala. \n"); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); else { //concateno para mejorar formato de mensaje respuesta strcat( mensaje, "Suscrito a la sala "); strcat( mensaje, "\""); strcat( mensaje, buffer); strcat( mensaje, "\""); strcat( mensaje, " satisfactoriamente.\n"); //agrego sala a cola de salas de usuario InsertarPalabra(&usuario[ide].salas,buffer); //coloco al usuario como conectado a la sala nueva usuario[ide].conectadousuario = 1; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //si la sala no existe, envio respuesta else { //concateno para mejorar formato de mensaje de respuesta strcat( mensaje, "La sala a suscribirse no existe. \n"); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); //eliminar una sala del servidor else if( formatovalido( expeliminasala, buffer) == 1 ) {

//bloquear area compartida, mutex pthread_mutex_lock (&mutex); //obtengo nombre de comando y parametro strcpy(funcion, primerapalabra(buffer, longitud)); //obtengo el numero de salas en el servidor numsalas = sistemasala[0].numerosala; //se verifica si la sala ya existe for(i = 1; i <= numsalas ; i++) { //si encontro la sala, cambia la bandera 'j' a true if(strcmp(sistemasala[i].nombresala, buffer) == 0 && sistemasala[i ].numerosala!= -1) { //elimino la sala sistemasala[i].numerosala = -1; //cambio bandera a true j = 1; //termino ciclo i = numsalas + 1; //si existe la sala, proceso peticion accion if ( j!= 0 ) { //concateno para mejorar formato de mensaje respuesta strcat( mensaje, "Sala "); strcat( mensaje, "\""); strcat( mensaje, buffer); strcat( mensaje, "\""); strcat( mensaje, " eliminada satisfactoriamente.\n"); //envio mensaje para cada usuario for(i = 1; i < clientes; i++) { if( eliminarelemento( &usuario[i].salas, buffer ) ) { //numero de salas a la que esta suscrito el //usuario ide. tam = tamano(&usuario[i].salas); //sino esta suscrito a mas salas, lo des-suscribo if(tam == 0) { //coloco al usuario como desconectado usuario[i].conectadousuario = 0; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente

send( usuario[i].idsocket, mensaje, strlen(mensaje)+1, 0); //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //si la sala no existe, envio respuesta else { //concateno para mejorar formato de mensaje de respuesta strcat( mensaje, "La sala a eliminar no existe. \n"); //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); //el usuario se des-suscribe de todas las salas else if( formatovalido( expdessuscribir, buffer) == 1 ) { //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //guardo mensaje de des-suscripcion strcat( mensaje, "De-suscrito de todas las salas satisfactoriamente. \n"); //coloco al usuario como desconectado usuario[ide].conectadousuario = 0; //coloco al usuario sin ninguna sala usuario[ide].salas=null; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); //el usuario termina la ejecucion de su cchat else if( formatovalido( expfuerachat, buffer) == 1 ) { //bloquear area compartida, mutex pthread_mutex_lock (&mutex); //obtengo nombre de comando strcpy(funcion, primerapalabra(buffer, longitud));

//coloco al usuario como fuera del servidor usuario[ide].conectadousuario = -1; //coloco al usuario sin ninguna sala usuario[ide].salas=null; //desbloquear area compartida, mutex pthread_mutex_unlock (&mutex); //envio respuesta al cliente send( usuario[ide].idsocket, funcion, strlen(funcion)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); //dejo de atender peticiones de este cliente break; else { //guardo mensaje de comando invalido strcat( mensaje, "\t'comando INVALIDO, SERVICIO NO ENCONTRADO'\n"); //envio respuesta al cliente send( usuario[ide].idsocket, mensaje, strlen(mensaje)+1, 0); //vacio buffers strcpy( mensaje, ""); strcpy( buffer, ""); fflush(stdout);

/* Proyecto 1: Redes ci4815 Programa: SocketServidor.c Realizado por: Lairon Acosta Version: 1.4 ----------------------------- Includes del sistema #include <stdio.h> #include <string.h> #include <stdlib.h> #include <Cola.h> #include <netdb.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/syscall.h> #include <sys/resource.h> #include <errno.h> #include <sys/stat.h> #include <unistd.h> #include <dirent.h> #include <fcntl.h> #include <sys/time.h> #include <regex.h> #include <SocketServidor.h> /****Implementacion de metodos*** /*funcion: realiza conexion de sockets arg1: puerto donde se hara la conexion return: descriptor de conexion int ConexionInetServidor (char *puerto) { //Declaracion de variables int fd_socket; struct sockaddr_in address; struct in_addr inaddr; struct hostent *host_cliente; //Abrimos el socket if(( fd_socket = socket (PF_INET, SOCK_STREAM, 0)) < 0) { printf("error abriendo el socket\n"); return -1; // /*

* Se rellenan los campos de la estructura Direccion, necesaria * para la llamada a la funcion bind() address.sin_family = AF_INET; address.sin_addr.s_addr =INADDR_ANY; //verifica si se obtuvo error en el puerto if (!(address.sin_port = htons(atoi(puerto))) ) { //dir PUERTO printf("error en el puerto\n"); return -1; // if ( bind( fd_socket, (struct sockaddr *) &address, sizeof (address) ) == -1) { printf("error realizando el bind\n"); close (fd_socket); return -1; /* * Se avisa al sistema que comience a atender llamadas de clientes if (listen (fd_socket, 1) == -1) { printf("error realizando el listen\n"); close (fd_socket); return -1; /* * Se devuelve el descriptor del socket servidor return fd_socket; /*funcion: realiza la aceptacion de la conexion con el cliente arg1: descriptor de conexion return: descriptor de conexion int AceptaConexionInetCliente (int fd_socket) { socklen_t longitudcliente; struct sockaddr cliente; int acepta; /* * La llamada a la funcion accept requiere que el parametro * Longitud_Cliente contenga inicialmente el tamano de la * estructura Cliente que se le pase. A la vuelta de la * funcion, esta variable contiene la longitud de la informacion * util devuelta en Cliente

longitudcliente = sizeof (cliente); acepta = accept (fd_socket, &cliente, &longitudcliente); if (acepta == -1) { return -1; /* * Se devuelve el descriptor en el que esta "enchufado" el cliente. return acepta; /*funcion: procesa los argumentos de la llamada Servidor1 arg1: cantidad de argumentos arg2: lista de argumentos arg3: cola que saldra modificada void procesarargumentosservidor(int numeroarg, char *argv[], Cola *cola) { char retorno[3][50]; // Comando de entrada: schat [-p <puerto>] [-s <sala>] if( strcmp(argv[1],"-p") == 0 ) { //copia el nombre en la posicion 0 del arreglo retorno strcpy(retorno[0],argv[2]); if( strcmp(argv[3],"-s") == 0 ) { //copia el archivo en la posicion 1 del arreglo retorno strcpy(retorno[1],argv[4]); else { printf ("Error: argumento -s no corresponde\n"); else if( strcmp(argv[3],"-p") == 0 ) { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[0],argv[4]); if( strcmp(argv[1],"-s") == 0 ) { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[1],argv[2]);

else { printf ("Error: argumento -s no corresponde\n"); else { printf ("Error: argumento -p no corresponde\n"); InsertarPalabra (cola, retorno[0]); InsertarPalabra (cola, retorno[1]); /*funcion: procesa los argumentos de la llamada Servidor2 arg1: cantidad de argumentos arg2: lista de argumentos arg3: cola que saldra modificada void procesarargumentosservidor2(int numeroarg, char *argv[], Cola *cola) { char retorno[3][50]; // Comando de entrada: schat [-p <puerto>] [-s] // Comando de entrada: schat [-s] [-p <puerto>] if( strcmp(argv[1],"-p") == 0 ) { //copia el nombre en la posicion 0 del arreglo retorno strcpy(retorno[0],argv[2]); if( strcmp(argv[3],"-s") == 0 ) { //copia el archivo en la posicion 1 del arreglo retorno strcpy(retorno[1],"actual"); else { printf ("Error: argumento -s no corresponde\n"); else if( strcmp(argv[2],"-p") == 0 ) {

else { //copia el nombre en la posicion 2 del arreglo retorno strcpy(retorno[0],argv[3]); if( strcmp(argv[1],"-s") == 0 ) { //copia el archivo en la posicion 3 del arreglo retorno strcpy(retorno[1],"actual"); else { printf ("Error: argumento -s no corresponde\n"); printf ("Error: argumento -p no corresponde\n"); InsertarPalabra (cola, retorno[0]); InsertarPalabra (cola, retorno[1]); /*funcion: obtiene primera palabra de una cadena arg1: cadena arg2: tamano de cadena return: primera palabra de la cadena char * primerapalabra(char *cad, int tam) { char * palabra = malloc(100); int i,j=0; for( i=0 ; (i < tam && cad[i]!=' ' && cad[i]!='\n') ; i++) { palabra[j]=cad[i]; cad[i]=' '; j++; palabra[j]='\0'; j=0; i = i+1; for( i ; i < tam && cad[i]!='\n' ; i++) { cad[j]=cad[i]; j++; cad[j]='\0';

return palabra; /*funcion: verifica si una cadena es una expresion regular valida arg1: expresion regular aplicar arg2: cadena de texto a verificar int: 1 si match, 0 sino. int formatovalido(char *expresion, char *texto) { regex_t regex; int rec; char msgbuf[100]; /* Compila la expresion regular rec = regcomp(&regex, expresion, 0); //verifico error if( rec ) { fprintf(stderr, "No se pudo compilar la expresion regular\n"); regfree(&regex); return 0; /* Ejecuta la expresion regular rec = regexec(&regex, texto, 0, NULL, 0); if (!rec ) { regfree(&regex); return 1; else if ( rec == REG_NOMATCH ) { regfree(&regex); return 0; else { regerror(rec, &regex, msgbuf, sizeof(msgbuf)); fprintf(stderr, "Regex match fallo: %s\n", msgbuf); regfree(&regex); return 0; /* libera el compilador si quieres usar regex de nuevo regfree(&regex);

/* Proyecto 1: Redes ci4815 Programa: SocketServidor.h Realizado por: Lairon Acosta Version: 1.2 /*Definiciones de tipos y estructuras de datos /* Estructura para manejar los usuarios var1: id socket de usuarios var2: nombre del usuario var3: conectado o desconectado (var3 = 1 si usuario esta conectado) (var3 = 0 si usuario esta desconectado) var4: Cola de salas a la que esta suscrito typedef struct datos { int idsocket; char nombreusuario[100]; int conectadousuario; Cola salas; Data; //variable de tipo Datos de usuario typedef Data datausuario; /* Estructura para manejar las salas var1: nombre de la sala var2: numero de la sala (var2 = -1 si sala esta eliminada) (var2 = 1 si sala no esta eliminada) typedef struct salas { char nombresala[100]; int numerosala; Salas; //variable de tipo Datos de salas typedef Salas salausuario; /*******Definiciones de metodos******* /*funcion: realiza conexion de sockets arg1: puerto donde se hara la conexion return: descriptor de conexion int ConexionInetServidor (char *puerto);

/*funcion: realiza la aceptacion de la conexion con el cliente arg1: descriptor de conexion return: descriptor de conexion int AceptaConexionInetCliente (int fd_socket); /*funcion: procesa los argumentos de la llamada Servidor1 arg1: cantidad de argumentos arg2: lista de argumentos arg3: cola que saldra modificada void procesarargumentosservidor(int numeroarg, char *argv[], Cola *cola); /*funcion: procesa los argumentos de la llamada Servidor2 arg1: cantidad de argumentos arg2: lista de argumentos arg3: cola que saldra modificada void procesarargumentosservidor2(int numeroarg, char *argv[], Cola *cola); /*funcion: obtiene primera palabra de una cadena arg1: cadena arg2: tamano de cadena return: primera palabra de la cadena char * primerapalabra(char *cad, int tam); /*funcion: verifica si una cadena es una expresion regular valida arg1: expresion regular aplicar arg2: cadena de texto a verificar int: 1 si match, 0 sino. int formatovalido(char *expresion, char *texto);

/* Proyecto 1: Redes ci4815 Programa: Cola.c Realizado por: Lairon Acosta Version: 1.9 #include <stdlib.h> #include <stdio.h> #include <string.h> #include <Cola.h> //funcion: inserta una palabra en la cola //out: la cola modificada void InsertarPalabra (Cola *cola, char *pal ) { apnodo nodo, nodoaux; if (((apnodo)malloc(sizeof(tipocaja)))==null) { printf("\nelemento no insertado por falta de memoria."); else { /*Creamos un nodo para el valor a insertar nodo = (apnodo)malloc(sizeof(tipocaja)); strcpy (nodo->palabra, pal); nodo->sig = NULL; /* si la cola está vacía, el *cola sera el nuevo nodo /* si no lo esta, insertamos el nuevo nodo al final de la cola if(*cola == NULL) { *cola = nodo; else { nodoaux = (*cola); while (nodoaux->sig!= NULL) { nodoaux = nodoaux->sig; nodoaux->sig = nodo; //funcion: borra una palabra de la cola //out: retorna 0 si borro o 1 sino borro int BorrarPrimero(Cola *cola) { apnodo nodo; int borro = 1; borro=1; //1= no borro, 0= si borro nodo = *cola; if (nodo == NULL) {

borro = 1; else { (*cola) = (*cola)->sig; nodo->sig = NULL; free(nodo); borro = 0; return (borro); //funcion: imprime la cola en pantalla //out: salida standar void ImprimirCola(Cola *cola) { apnodo nodo; nodo = *cola; if (cola!=null) { while (nodo->sig!= NULL){ printf(" -> %s ", nodo->palabra); printf("\n"); nodo = nodo->sig; printf(" -> %s ", nodo->palabra); printf("\n"); printf("\n"); else { printf(" Lista vacia\n\n"); //funcion: borra una palabra de la cola //out: retorna 0 si borro o 1 sino borro char * dameprimero(cola *cola) { apnodo nodo; int borro = 1; char *word =malloc(300); borro=1; //1= no borro, 0= si borro nodo = *cola; if (nodo == NULL) { borro = 1; else { strcpy(word,nodo->palabra); (*cola) = (*cola)->sig; nodo->sig = NULL; free(nodo); borro = 0; return word;