formato para documentar proyecto

10
Programación en ambiente cliente servidor Programación de cliente y servidor en lenguaje C Espinoza Manriquez Edgar Salvador y Vega Arroyo José Raúl a ITESI, Irapuato Gto., México Abstract Este reporte contiene información sobre la programación de un servidor en lenguaje c utilizando un compilador del entorno Windows el cual será trasladado a UNIX en linux con distribución de Ubuntu. El cual incluye información del uso y manejo de sockets para la conexión mediante TCP entre 2 SO con diferente arquitectura. 1. Introducción Con este reporte pretende darse a conocer la bitácora de la programación de un servidor en lenguaje C, el cual deberá hacer conexión con un cliente programado en c# el cual debe funcionar en el SO Windows y posteriormente lograr una conexión entre alguna distribución de Linux y OSX. Este proyecto fue divido en dos partes, separando de la misma manera el grupo completo, teniendo así una parte programando en c y la otra parte en c# para de esta forma llegar a un producto final el cual será la conexión que deberemos establecer con la pareja que nos haya tocado. Cabe aclarar que este reporte pertenece solo a la parte de programación en C. Este programa correrá en un equipo con las siguientes especificaciones: HP Pavilion dm4 SO Windows 8.1 64bits (Ubuntu 14.10 64bits para el programa corriendo en Linux) RAM de 6gb HDD de 750 gb Procesador Intel® Core™ i5-2450M CPU @ 2.50Hz Para llevar a cabo este programa necesitamos de cierto software y recursos extra en caso de no haberlos tenido ya instalados en el equipo de trabajo. Como compilador para Windows utilizamos DevC++ para llevar a cabo el revisado y desarrollo del programa, además de instalar una librería especial diseñada para la manipulación de sockets y poder así hacer conexión y comunicación con el cliente. Esta librería está disponible en la mayoría de los ordenadores actuales sin embargo es posible que no esté instalada en algunos. En nuestro caso no fue necesario hacer la instalación ni del compilador ni de la librería puesto que en semestres pasados ya habíamos utilizado el compilador para trabajos o proyectos referentes al semestre y la librería ya se encontraba disponible en la laptop utilizada para hacer los programas.

Upload: edgar-espinoza

Post on 18-Nov-2015

29 views

Category:

Documents


0 download

DESCRIPTION

huhoh

TRANSCRIPT

  • Programacin en ambiente cliente servidor

    Programacin de cliente y servidor en lenguaje C

    Espinoza Manriquez Edgar Salvador y Vega Arroyo Jos Ral

    aITESI, Irapuato Gto., Mxico

    Abstract

    Este reporte contiene informacin sobre la programacin de un servidor en lenguaje c utilizando un compilador del

    entorno Windows el cual ser trasladado a UNIX en linux con distribucin de Ubuntu. El cual incluye informacin del uso

    y manejo de sockets para la conexin mediante TCP entre 2 SO con diferente arquitectura.

    1. Introduccin

    Con este reporte pretende darse a conocer la bitcora de la programacin de un servidor en lenguaje

    C, el cual deber hacer conexin con un cliente programado en c# el cual debe funcionar en el SO Windows y

    posteriormente lograr una conexin entre alguna distribucin de Linux y OSX.

    Este proyecto fue divido en dos partes, separando de la misma manera el grupo completo, teniendo as una

    parte programando en c y la otra parte en c# para de esta forma llegar a un producto final el cual ser la

    conexin que deberemos establecer con la pareja que nos haya tocado. Cabe aclarar que este reporte pertenece

    solo a la parte de programacin en C.

    Este programa correr en un equipo con las siguientes especificaciones:

    HP Pavilion dm4

    SO Windows 8.1 64bits (Ubuntu 14.10 64bits para el programa corriendo en Linux)

    RAM de 6gb

    HDD de 750 gb

    Procesador Intel Core i5-2450M CPU @ 2.50Hz

    Para llevar a cabo este programa necesitamos de cierto software y recursos extra en caso de no haberlos tenido

    ya instalados en el equipo de trabajo. Como compilador para Windows utilizamos DevC++ para llevar a cabo

    el revisado y desarrollo del programa, adems de instalar una librera especial diseada para la manipulacin

    de sockets y poder as hacer conexin y comunicacin con el cliente.

    Esta librera est disponible en la mayora de los ordenadores actuales sin embargo es posible que no est

    instalada en algunos. En nuestro caso no fue necesario hacer la instalacin ni del compilador ni de la librera

    puesto que en semestres pasados ya habamos utilizado el compilador para trabajos o proyectos referentes al

    semestre y la librera ya se encontraba disponible en la laptop utilizada para hacer los programas.

  • Espinoza Manriquez Edgar Salvador 2

    Para la parte de conexin con UNIX ser utilizada la distribucin de Linux UBUNTU donde est SO tendr

    alojado al Servidor programado en C para hacer la conexin con OSX que tendr alojados el cliente

    programado en C#.

    Como compilador utilizamos GCC para distribuciones de Linux, en esta distribucin tampoco fue necesario

    instalar la librera de manejo de sockets ya que el SO ya trae precargada la misma.

    2. Desarrollo

    Como primera prctica debimos investigar sobre el manejo de sockets en Windows mediante la

    librera winsock.h, la cual es la que permite la manipulacin de estos dentro del entorno de DevC++ adems

    de los diferentes tipos de sockets que existen y los dominios que pueden manejar.

    Para empezar a codificar deberemos crear un nuevo proyecto al cual le dimos el nombre de uici, para

    la codificacin tomamos de base el cdigo que viene en el libro de Unix Programacin Prctica el cual nos

    proporcion el maestro.

    2.1. Servidor (Windows)

    El entorno utilizado para programar el servidor en c fue DevC++ versin 5.04 para 64 bits tomando como

    referencia un cdigo ya establecido por el profesor, el cual se conecta con el cliente programado en c# a base

    de sockets y seleccionando el primer puerto disponible para generar la conexin y comunicacin con el

    mismo, este servidor permanece activo hasta que el cliente termine el proceso de conexin y cierre el

    programa por lo que el servidor cerrara la comunicacin solo si se mata el proceso con un valor nulo.

    Usando la librera dedicada al manejo de sockets (winsock.h y linwsock32.a) fue posible llevar a cabo el

    siguiente programa:

    typedef unsigned short u_port_t;

    int u_open(u_port_t port);//*****

    int u_listen (int fd, char* hostn);

    #include

    #include

    #include

    #include "uici.h"

    #define MAXBACKLOG 10

    SOCKET sock;

    int u_open (u_port_t port)

    Librera dedicada al manejo de sockets

    Cabecera programada para llamada de funciones

    Tipo de dato socket

    Definimos el tipo short u_port_t.

    Abre descriptor de archivo (Leer el puerto)

    identificador ligado a "port". Devuelve descriptor de

    archivo que escucha

  • Espinoza Manriquez Edgar Salvador 3

    {

    int SOCKET; //descriptor de archivo del socket

    struct sockaddr_in servidor;

    int len = sizeof(struct sockaddr);

    WSADATA w;

    int error=WSAStartup(0x0202,&w);

    if (error)

    {

    printf("No se puede inicializar el socket");

    return FALSE;

    }

    if (w.wVersion!=0x0202);

    {

    printf("La version no es la correcta");

    return FALSE;

    }

    if((SOCKET =socket (AF_INET,SOCK_STREAM,0))

  • Espinoza Manriquez Edgar Salvador 4

    int u_listen (int fd, char* hostn)

    {

    struct sockaddr_in cliente;

    int len = sizeof (struct sockaddr);

    int retval;

    int cc;

    char buf[1024];

    struct hostent * hostptr;

    while (((retval= accept(fd,(struct sockaddr*)(&cliente),&len))==1) && (errno==4));

    if(retval==-1)

    return retval;

    hostptr = gethostbyaddr((char*)&(cliente.sin_addr.s_addr),4,AF_INET);

    if (hostptr==NULL)

    strcpy(hostn,"Desconocido");

    else

    strcpy(hostn,(* hostptr).h_name);

    do{

    cc=recv(retval,buf,sizeof(buf),0);

    if (cc==0) exit (0);

    if(cc>0)

    printf("\n %s dice %s",hostn,buf);

    else

    {

    printf("\n %s esta desconectado",hostn);

    closesocket(fd); break;

    }

    }while(1);

    closesocket(fd);

    retval= WSACleanup();

    if(retval==SOCKET_ERROR)

    {

    printf("Error limpiando la libreria WinSock");

    return -1;

    }

    return retval;

    }

    Escucha para detectar la solicitud del nodo

    especificado en el puerto dado

    El servidor usa est funcin para escuchar la

    comunicacin; este se bloquea hasta recibir una

    solicitud remota del puerto vinculado con el

    descriptor de archivo dado asignado a hostn

    El servidor seguir estableciendo comunicacin

    hasta que se reciba un valor nulo, mandando un

    error y limpiando la librera.

  • Espinoza Manriquez Edgar Salvador 5

    int main(int argc, char *argv[]) {

    int fd;

    char clienteremoto[20];

    fd= u_open(23);

    if (fd!=-1)

    if(u_listen(fd,clienteremoto)!=-1);

    getch();

    return 0;

    }

    2.2. Servidor (Linux fallido)

    Para la programacin del servidor en linux se tom de referencia el programa hecho en windows, pero a

    pesar de cambiar las libreras correspondientes a Windows, no fue posible adaptarlo por completo por lo que

    se decidi hacer un programa nuevo basado en uno existente el cual fue modificado para las funciones

    necesarias al proyecto.

    A continuacin se explicar el cdigo basado en el usado en Windows y el libro Unix programacin

    prctica de las pginas 439 y 440 y la cabecera (uici.h) localizada en la pgina 599:

    #include

    #include

    #include

    #include

    #include uici.h

    Void main (int argc, char *argv[])

    {

    u_port_t portnumber;

    int listenfd;

    int communfd;

    char client [MAX_CANON]

    int bytes_copied;

    if (argc != 2)

    {

    fprintf(stderr, Usage: %s Puerto\n, argv[0];

    exit(1);

    }

    El servidor seguir estableciendo comunicacin

    hasta que el cliente termine su proceso, es

    entonces cuando la conexin termina

  • Espinoza Manriquez Edgar Salvador 6

    portnumber = (u_port_t) atoi(argv[1]);

    if ((listenfd = u_open (portnumber)) == -1 )

    {

    u_error(No estabecido para establecer conexin con puerto);

    exit(1);

    }

    while((communfd = u_listen(listenfd, client)) != -1)

    {

    fprintf(stderr, Conexin establecida con %s \n,client);

    }

    exit (0);

    }

    Cabecera:

    Typedef unsigned short u_port_t;

    int u_open (u_port_t port);

    int u_listen (int fd, char *hostn);

    ssize_t u_read(int fd, void *buf, size_t nbyte);

    ssize_t u_write(int fd, void *buf, size_t nbyte);

    2.3. Servidor (Linux funcional)

    Este cdigo final fue hecho basado en investigacin por libros y foros en internet para generar un servidor

    el cual fue trabajado en conjunto con algunos compaeros para acelerar su funcionamiento, el siguiente

    cdigo fue modificado para la necesidad establecida por el proyecto el cual tiene 2 ficheros de nombre server

    y socket_server respectivamente, una cabecera dedicada a cada fichero con el mismo nombre y un makefile

    que permite la compilacin desde terminal en ubuntu.

    SERVER

    #include "Socket_server.h"

    #include

    #include

    main ()

    {

    int Socket_Servidor;

    int Socket_Cliente;

    char Cadena[100];

    Socket_Servidor = Abre_Socket_Inet ("port");

    if (Socket_Servidor == -1)

    Descriptores del socket

    server y del socket

    cliente

    Apertura del socket server con el

    servicio dado de alta el cual fue

    ingresado mediante consola con el

    nombre port y asignado el puerto

    17500

  • Espinoza Manriquez Edgar Salvador 7

    {

    printf ("No se puede abrir socket servidor\n");

    exit (-1);

    }

    Socket_Cliente = Acepta_Conexion_Cliente (Socket_Servidor);

    if (Socket_Servidor == -1)

    {

    printf ("No se puede abrir socket de cliente\n");

    exit (-1);

    }

    Lee_Socket (Socket_Cliente, Cadena, 5);

    printf ("Soy Servidor, he recibido : %s\n", Cadena);

    strcpy (Cadena, "Adios");

    Escribe_Socket (Socket_Cliente, Cadena, 6);

    /* Se cierran los sockets */

    close (Socket_Servidor);

    }

    SOCKET SERVER

    int Lee_Socket (int fd, char *Datos, int Longitud)

    {

    int Leido = 0;

    int Aux = 0;

    if ((fd == -1) || (Datos == NULL) || (Longitud < 1))

    return -1;

    while (Leido < Longitud)

    {

    Aux = read (fd, Datos + Leido, Longitud - Leido);

    if (Aux > 0)

    {

    Leido = Leido + Aux;

    }

    else

    {

    if (Aux == 0)

    return Leido;

    Funcin que espera y acepta

    la conexin del cliente, el

    cual lee la informacin

    suponiendo que va a enviar 5

    caracteres, esto debido a que

    si se ingresa un nmero

    mayor el servidor no

    imprime nada hasta que el

    numero permitido se cumpla

    ms 1 caracter ms que

    ocupa el espacio de enter

    en cdigo ASCII

    Esta Funcin lee los

    datos del socket

    generado, supone que se

    le pasa a un buffer un

    nuero determinado de

    bytes leidos, en caso de

    recibir un 0 o -1 esta lo

    interpreta como error y

    genera comprobacin de

    parametros

  • Espinoza Manriquez Edgar Salvador 8

    if (Aux == -1)

    {

    switch (errno)

    {

    case EINTR:

    case EAGAIN:

    usleep (100);

    break;

    default:

    return -1;

    }

    }

    }

    }

    return Leido;

    }

    int Escribe_Socket (int fd, char *Datos, int Longitud)

    {

    int Escrito = 0;

    int Aux = 0;

    if ((fd == -1) || (Datos == NULL) || (Longitud < 1))

    return -1;

    while (Escrito < Longitud)

    {

    Aux = write (fd, Datos + Escrito, Longitud - Escrito);

    if (Aux > 0)

    {

    if (Aux == 0)

    return Escrito;

    else

    return -1;

    }

    }

    /* Devolvemos el total de caracteres leidos */

    return Escrito;

    }

    En cualquier caso de error la variable declarada

    errno indica el tipo de error cometido:

    EINTR para cualquier interrupcin de sistema

    antes de leer ningn dato

    EGAIN para cuando el socket no est disponible

    Ambos errores tienen un rango de espera de 100

    microsegundos los cuales pueden ser modificados

    Si existe un error diferente el programa provoca

    que salga de la funcin con error

    Una vez devueltos los caracteres ledos

    Escribe_Socket devuelve el nmero de

    bytes escritos o el error para despus

    comprobar los parmetros de entrada.

    Despus entra un bucle que se detiene

    hasta que hayamos escrito todos los

    caracteres que nos han indicado, si

    hemos conseguido escribir caracteres,

    este actualiza la variable Escrito.

    Una vez cerrado el socket devuelve un

    nmero de caracteres ledos, en caso de

    error devuelve 1

  • Espinoza Manriquez Edgar Salvador 9

    CABECERA SOCKET (Socket.h)

    #ifndef SOCKET_H_INCLUDED

    #define SOCKET_H_INCLUDED

    int Lee_Socket (int fd, char *Datos, int Longitud);

    int Escribe_Socket (int fd, char *Datos, int Longitud);

    #endif // SOCKET_H_INCLUDED

    CABECERA SOCKET SERVER (socket_server.h)

    #ifndef SOCKET_SERVIDOR_H_INCLUDED

    #define SOCKET_SERVIDOR_H_INCLUDED

    int Abre_Socket_Inet (char *Servicio);

    int Abre_Socket_Unix (char *Servicio);

    int Acepta_Conexion_Cliente (int Descriptor);

    #endif // SOCKET_SERVIDOR_H_INCLUDED

    MAKEFILE

    all : Socket.o Socket_server.o server

    CPPFLAGS = -g -I.

    server : server.c

    cc -g -I. Socket.o Socket_server.o server.c -o server

    clean :

    rm *.o server

    Llamada de las funciones

    Lee_Socket y Escribe Socket para el

    uso del fichero con el mismo

    nombre (Socket.c)

    Llamada de las funciones

    Abre_Socket_Inet para conexin

    AF_INET

    Abre_Socket_Unix para conexin

    con sockets AF_UNIX

    Y Acepta_Conexion_Cliente para

    llevar a cabo la funcin de

    conexin y comunicacin

    El comando de linux make nos

    ayuda a compilar nuestros

    programas. Presenta muchas

    ventajas para programas grandes, en

    los que hay muchos ficheros fuente

    (muchos .c y muchos .h) repartidos

    por varios directorios.

  • Espinoza Manriquez Edgar Salvador 10

    References

    Ttulo Unix programacin prctica

    Autores Kay A. Robbins, Steven Robbins

    Edicin ilustrada Editor Pearson Educacin, 1997

    ISBN 9688809594, 9789688809594

    N. de pginas 659 pginas

    Unix : programacin avanzada

    Autor Francisco Manuel Mrquez Garca Edicin 3

    Editor Ra-Ma, 2004

    ISBN 8478976035, 9788478976034 N. de pginas 632 pginas