¡Recomienda este blog!

lunes, 11 de abril de 2011

Código Fuente Cliente-Servidor: Ahorcado remoto.

Código fuente del Servidor:

/*************************************************************************
*
* Servidor del juego Ahorcado en TCP.
* Asignatura: Redes II.
* Autores:
* Gabriel Cebrián Márquez.
* Estefanía Coronado Calero.
* Iván Durango Blanco.
*
************************************************************************/

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 
#include 
#include 

#include 
/*extern int errno;*/

#include "error.h"
#include "socket_utils.h"

#define _USE_BSD
#define QLEN     32 /* Longitud máxima de la cola de conexiones */
#define BUFSIZE   4096
#define MAXDICT     32 /* Máximo tamaño de la palabra del ahorcado */
#define MAXLINEA MAXDICT + 10
#define NUM_PALABRAS     15

void reaper(int);
int escogeAleatorio();
int ahorcadoSrv(int desc);

/*************************************************************************
*
* main - Servidor concurrente para el servicio del ahorcado remoto.
*
*************************************************************************/

int main(int argc, char *argv[])
{
char *service = "8041"; /* Nombre del servicio o número de puerto */
struct sockaddr_in fsin; /* Dirección del cliente   */
unsigned int alen;  /* Tamaño de la dirección del cliente  */
int msock;   /* Socket del servidor maestro   */
int ssock;   /* Socket del servidor esclavo   */

switch (argc)
{
case 1:
break;
default:
errexit("Uso del programa: Ahorcado_servidor\n");
}

/* Se crea un socket pasivo */
msock = passiveTCP(service, QLEN);
(void) signal(SIGCHLD, reaper);

while (1)
{
alen = sizeof(fsin);

/* Cambiamos el identificador del socket */
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);

if (ssock < 0)
{
if (errno == EINTR)
continue;
errexit("Error ACCEPT: %s\n", strerror(errno));
}

switch (fork())
{
case 0:  /* Hijo */
(void) close(msock);
exit(ahorcadoSrv(ssock));
default: /* Padre */
(void) close(ssock);
break;
case -1:
errexit("Error FORK: %s\n", strerror(errno));
}
}
}

/*************************************************************************
*
* ahorcadoSrv - Función que gestiona el juego en el servidor.
* 
*************************************************************************/

int ahorcadoSrv(int desc)
{
/* Diccionario de palabras para el juego */
char diccionario[NUM_PALABRAS][MAXDICT] = { 
"CARACOL",
"MOTOCICLETA",
"HORMIGA",
"GUACAMAYO",
"HECHICERO",
"JUGUETE",
"LICENCIA",
"INSECTICIDA",
"JINETE",
"LADRILLO",
"LEVADIZO",
"JEROGLIFICO",
"LEVITACION",
"IMPACIENCIA",
"IMPERMEABILIDAD"};

char auxiliar[MAXLINEA];
char solucion[MAXLINEA] = "Correcta: "; /* Array auxiliar para mostrar la palabra correcta al final. */
char ahorcado[] = "AHORCADO"; /* Array auxiliar para mostrar ahorcado*/
char buffer[BUFSIZ];
char solucionSrv[MAXDICT + 26] = "La palabra a adivinar es: "; /* Solución que se mostrará en el servidor. */

int cc;
int aleatorio = escogeAleatorio(); /* Indice aleatorio del array*/

int i;
int encontrados;
int NumCaracteresAEncontrar = 0;
int errores = 0;

/* Mostramos la palabra que se debe adivinar en la terminal del servidor. */
printf("%s\n", strcat(solucionSrv, diccionario[aleatorio]));

/* Inicializamos el vector auxiliar a espacios vacíos. */
for (i = 0; i < MAXLINEA; i++)
auxiliar[i] = ' ';

/* Colocamos los asteriscos de la palabra elegida. */
for (i = 10; diccionario[aleatorio][i-10] != '\0'; i++)
auxiliar[i] = '*'; 
auxiliar[i] = '\0';

/* Pongo el limite de caracteres que deben ser encontrados. */
NumCaracteresAEncontrar = i - 10;

/* Enviamos la primera pista al cliente, todavía sin haber realizado ningún intento. */
if (write(desc, auxiliar, MAXLINEA) < 0) 
errexit("Error WRITE (primera pista): %s\n", strerror(errno));

/* Mientras no superemos el número de errores, no hayamos ganado y leamos algo del cliente */
while ((NumCaracteresAEncontrar > 0) && (errores < 8) && (cc = read(desc, buffer, sizeof(buffer))) )
{
if (cc < 0)
errexit("No se ha leído la letra correctamente: %s\n", strerror(errno));

/* Inicializamos encontrados, que servirá para ver si se encuentra la letra recibida todavía sin descubrir. */
encontrados = 0;

/* Recorremos todas las letras de la palabra del diccionario */
for (i = 10; diccionario[aleatorio][i-10] != '\0'; i++)
{
/* Miramos que no la hayamos introducido anteriormente. */
if ((toupper(buffer[0]) == diccionario[aleatorio][i-10]) && (toupper(buffer[0]) != auxiliar[i]))
{
auxiliar[i] = toupper(buffer[0]);
encontrados++;
NumCaracteresAEncontrar--;
}
}

if (encontrados == 0) errores++;

/* Ponemos la palabra AHORCADO según el número de errores. */
for (i = 0; i < errores; i++)
auxiliar[i] = ahorcado[i];

if ( NumCaracteresAEncontrar != 0 && errores < 8)
{
if (write(desc, auxiliar, MAXLINEA) < 0) 
errexit("Error WRITE (envío pista): %s\n", strerror(errno));
}

}


if (errores >= 8)
{
if (write(desc, "FIN DE LA PARTIDA. ¡Has sido ahorcado!", MAXLINEA) < 0) 
errexit("Error WRITE (envío final de partida): %s\n", strerror(errno));
}
else
{
if (write(desc, "FIN DE LA PARTIDA. ¡Has ganado!", MAXLINEA) < 0)
errexit("Error WRITE (envío final de partida): %s\n", strerror(errno));
}

/* Enviamos la palabra correcta */
if (write(desc, strcat(solucion, diccionario[aleatorio]), MAXLINEA) < 0)
errexit("Error WRITE (envío solución): %s\n", strerror(errno));

/* Cerramos socket */
close(desc);
return 0;
}

/*************************************************************************
*
* escogeAleatorio - Función que gestiona el juego en el servidor.
* 
*************************************************************************/

int escogeAleatorio()
{
int i, n, aleatorio, P, U;

/* Indices, entre 0 y NUM_PALABRAS-1. Son NUM_PALABRAS palabras*/
P = 0;

U = NUM_PALABRAS-1;

srand(time(NULL));

aleatorio = P+(int)(((U-P+1.0)*rand())/(RAND_MAX+1.0));

return aleatorio;
}

/*************************************************************************
*
* reaper - Limpia los hijos en estado zombie.
* 
*************************************************************************/

void reaper(int sig)
{
int status;

while (wait3(&status, WNOHANG, (struct rusage *)0) >= 0)
/* empty */;
}

Código fuente del Cliente:

/*************************************************************************
*
* Cliente del juego Ahorcado en TCP.
* Asignatura: Redes II.
* Autores:
* Gabriel Cebrián Márquez.
* Estefanía Coronado Calero.
* Iván Durango Blanco.
*
************************************************************************/

#include 
#include 
#include 
#include 
#include 

#include 
/*extern int errno;*/

#include "error.h"
#include "socket_utils.h"

/* Librerías incluídas */
#include "miconio.h"

int ahorcadoCli(const char *host, const char *service);
int comparacion(char *c1);
void leerDeServidor(char *buf, int socket);

#define MAXLINEA  42 /* Máximo tamaño de la línea que recibiremos. */

/*************************************************************************
*
* Main - Cliente ahorcado TCP.
*
************************************************************************/

int main(int argc, char *argv[])
{
char *host = "localhost"; /* Host que se usa si no se indica ninguno */
char *service = "8041"; /* Nombre del servicio por defecto     */
char nombreServidor[256]; /* Almacenará el nombre del servidor, si fuera necesario. */

switch (argc)
{
case 1:
printf("Indica el nombre del host o IP al que conectar: ");
scanf("%s", nombreServidor);
fflush(stdin);
host = nombreServidor;
break;
case 2:
host = argv[1];
break;
default:
fprintf(stderr, "Uso del programa: Ahorcado_cliente [host]\n");
exit(1);
}
ahorcadoCli(host, service);
exit(0);
}

/*************************************************************************
*
* ahorcadoCli - Función que gestiona el juego para el cliente.
*
************************************************************************/

int ahorcadoCli(const char *host, const char *service)
{
char buf[MAXLINEA+1]; /* Buffer para intercambio de información */
int socket;   /* Descripción del socket    */
int outchars;  /* Número de caracteres enviados   */

socket = connectTCP(host, service);

printf("\n=======================================");
printf("\n          AHORCADO REMOTO");
printf("\n=======================================");
printf("");
printf("\nInstrucciones: El servidor elegirá aleatoriamente una palabra que usted tendrá");
printf("\n  que adivinar.");
printf("\nDispone de 8 intentos para acertarla. En cada intento podrá elegir una letra.");
printf("\nSi la palabra a adivinar la contiene, esta aparecerá en su lugar.");
printf("\nSi usted repite una letra se le añadirá un fallo a su lista. El juego finalizará");
printf("\n  si usted adivina la palabra o por el contrario se muestra la palabra AHORCADO.");
printf("\n\n\nErrores:  Palabra a adivinar:");
printf("\n\n");

/* Leemos la cadena del servidor donde se nos ofrece la primera pista. */
leerDeServidor(buf, socket);
printf("%s\n",buf);

while (buf[0] = getch())
{
if (((buf[0] >= 'A') && (buf[0] <= 'Z')) || ((buf[0] >= 'a') && (buf[0] <= 'z')))
{ 
buf[MAXLINEA] = '\0'; /* Fin de linea */
outchars = strlen(buf);
if (send(socket, buf, outchars) < 0)
errexit("Error SEND: %s\n", strerror(errno));;

/* Se lee del servidor */
leerDeServidor(buf, socket);

if(comparacion(buf) == 1)
{
printf("%s\n",buf); /* Hemos llegado al final, ganando o perdiendo, imprimimos dos líneas. */
leerDeServidor(buf, socket);
printf("%s\n",buf);

close(socket);
exit(0);
}

printf("%s\n",buf);
}
}
}

/*************************************************************************
*
* comparacion - Función que determina cuando finaliza el cliente, acabará
* cuando el servidor responde FIN.
* Si hemos llegado al final retorna 1. De lo contrario retorna 0.
*
************************************************************************/

int comparacion(char *c1)
{ 
char palabra[] = "FIN";
int i;

for (i = 0; i<3; i++)
{
if (c1[i]!=palabra[i])
return 0;
}

return 1;
}

/*************************************************************************
*
* leerDeServidor - Función que recoje lo que el servidor envía.
*
**************************************************************************/

void leerDeServidor(char *buf, int socket)
{
int inchars;
int n;

for (inchars = 0; inchars < MAXLINEA; inchars += n)
{
n = read(socket, &buf[inchars], MAXLINEA - inchars);

if (n < 0)
errexit("Error READ: %s\n", strerror(errno));
}
}

Link para descargar el código fuente:

Codigo_fuente_ahorcado

Para más información sobre como ejecutar, como a sido diseñado, etc visitar:

http://aprendiendo2veces.blogspot.com/2011/04/aplicacion-cliente-servidor-ahorcado.html

2 comentarios:

Anónimo dijo...

Hola q tal, q bibliotecas tengo q enlazar a la hora de compilar, es decir como lo compilo

Iván Durango Blanco. dijo...

Hola, para compilar se puede utilizar el compilador GCC de Linux introduciendo los
siguientes comandos según queramos para el cliente o el servidor:

Para el cliente:

gcc Ahorcado_cliente.c socket_utils.c error.c miconio.c -o Ahorcado_cliente

Para el servidor:

gcc Ahorcado_servidor.c socket_utils.c error.c -o Ahorcado_servidor

Las bibliotecas:
socket_utils.c error.c miconio.c

Las subo para que las puedas descargar. Además te añado tambien el makefile, con el que puedes compilar ejecutando desde Linux:

$ make all

Saludos!!

Publicar un comentario