Formato Para Documentar Proyecto
-
Upload
edgar-espinoza -
Category
Documents
-
view
29 -
download
0
description
Transcript of Formato Para Documentar Proyecto
-
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