- Un cliente TCP para hacer pruebas con los servidores
- Un servidor TCP iterativo
- Un servidor TCP concurrente
- Un cliente SMTP
- Un cliente POP3
1º -> El cliente TCP, para probar el servidor TCP que veremos en 2º lugar.
El cliente es muy simple, está totalmente comentado y lo único que hace es enviar una cadena de texto que introduce el usuario al servidor y leer la respuesta. (Muy útil para el nivel 13 de Hackerslab una vez se haya resuelto lo del problema del camino más corto)
/************************/
/* CLIENTE TCP */
/************************/
#include
#include
#include
#include
#include
#include
#include
#include
#define SI "s" /*Declaración de constantes*/
void main(void)
{ /*Declaración de variables*/
struct sockaddr_in direccion;
int i,s,contador,length,longitud;
char DATA[256];
char fin[5];
char respuesta[5];
char repeticion[5];
char datos[256];
/*Vacío cadena dirección*/
bzero((char*)&direccion,sizeof(direccion));
/*Imprimo cartel en pantalla*/
printf("_______________________________________\n");
printf(" \n");
printf(" CLIENTE TCP \n");
printf("_______________________________________\n");
printf(" \n");
/*Si el servidor no tuviera un puerto de conexión fijo y nos hubiera dicho el número de puerto por el que tenemos que conectarnos, usaríamos la siguiente función para que el usuario nos dijera el nº de puerto*/
/*printf("INTRODUCE el nº puerto al que conectar \n");*/
/* scanf("%d",fin);*/ /*Leemos nº de puerto*/
/*puerto=atoi(fin);*/ /*Convierte cadena en entero*/
/**DIR SERVIDOR**/
direccion.sin_addr.s_addr=inet_network("127.0.0.1");
/*Dirección del servidor*/
direccion.sin_addr.s_addr=inet_addr("127.0.0.1");
direccion.sin_family=AF_INET;/*Familia de Protocolo AF_INET*/
direccion.sin_port=htons(1999);/*Usamos el puerto fijo 1999*/
s=socket(AF_INET,SOCK_STREAM,0); /*Creamos un socket*/
if(s<0) /*Si hay un error al crearlo, lo mostramos en pantalla*/ { printf("ERROR al crear el socket\n"); } printf("\n"); printf("Introduce la cadena a enviar: "); /*Petición de datos*/ /*Leemos los datos y medimos su longitud*/ gets(DATA);longitud=strlen(DATA); /*Imprimimos la longitud de la cadena por pantalla*/ printf("la longitud es : %d \n", longitud); /*********************/ if(connect(s,(struct sockaddr*)&direccion,sizeof(direccion))<0) { /*Intentamos conectar con el servidor*/ printf("ERROR al conectar "); /*Si falla imprime un error*/ } else { printf("he aceptado la conexion\n"); } /***********************/ do{ /*Repite hasta que el cliente no quiera introducir más datos*/ if(send(s,DATA,strlen(DATA),0)<0) /*Enviamos datos al servidor*/ { printf("ERROR AL ENVIAR \n"); } else /*Si no hay error al enviar...*/ { bzero(datos,sizeof(datos)); /*Vacía la cadena datos*/ read(s,datos,sizeof(datos)); /*Lee el mensaje del servidor*/ printf("Mensaje Recibido: "); /*y lo imprime en pantalla*/ for(i=0;i
Lo que hace este servidor es recibir la cadena que manda el cliente, encriptarla con una función muy simple (a la vez que chapucera) y devolverla al cliente.
El proceso de encriptación, permuta la posición de letras correlativas, es decir... Hola se vuelve oHal y adios se vuelve daois.
/********************************/
/* SERVIDOR ITERATIVO */
/********************************/
#include
#include
#include
#include
#include
#define TRUE 1 /*Definición de constantes*/
main () /*Programa Principal*/
{
char buf_in[1024]; /*Definición de variables*/
char buf_out[1024];
int rval,caracter,caracter0;
int i,contador;
int sock,length;
struct sockaddr_in server ;
int msgsock;
sock=socket(AF_INET,SOCK_STREAM,0); /*Creamos el socket*/
if(sock<0){ /*Si el identificador de socket es negativo...*/ /*Imprime por pantalla el error*/ fprintf(stderr,"Abriendo un socket de tipo stream. \n"); exit(1); /*y sale del programa*/ } server.sin_family=AF_INET; /*Familia de protocolo AF_INET*/ server.sin_addr.s_addr=inet_network("127.0.0.1"); /*Dirección del servidor*/ server.sin_addr.s_addr=inet_addr("127.0.0.1"); server.sin_port=htons(1999); /*Nº de puerto*/ /*Asociamos socket a la dirección del servidor*/ if(bind(sock,&server,sizeof(server)) ){ fprintf(stderr,"Nombrando al socket de tipo stream.\n"); /*Si ha habido un error, se imprime en pantalla y sale del programa*/ exit(1); } /*Función que averigua el nº de puerto que ha asignado el sistema operativo, en el caso de que se le pida a éste que asigne un puerto automáticamente*/ /* length=sizeof(server); if(getsockname(sock,&server,&length)) { fprintf(stderr,"Obteniendo el puerto para el socket"); exit(1);}*/ printf("El socket tiene el puerto %d\n", ntohs(server.sin_port)); /*Nos quedamos a la escucha con una cola para 5 clientes*/ listen(sock,5); do { /*Repite el bucle infinítamente*/ /*Aceptamos la petición de conexión del cliente*/ msgsock=accept(sock,0,0); /*Si ha habido un fallo en la aceptación de conexión...*/ if(msgsock==-1) /*...imprime el error por pantalla*/ fprintf(stderr,"Fallo en la función accept.\n"); /*Si todo ha ido bien y mientras el cliente no cierre la conexión...*/ else do bzero(buf_in,sizeof(buf_in)); /*Vacía el búfer de entrada*/ /*Lee datos del cliente y si obtiene un error...*/ if((rval=read(msgsock,buf_in,1024))<0) /*...lo imprime en pantalla*/ perror("ERROR: Leyendo el mensaje.\n"); if(rval==0) /*Si lee un NULL (Desconexión) del cliente...*/ /*...imprime que finaliza la conexión*/ printf("Finalizando la conexion.\n"); else /*Si no...*/ /*Imprime el mensaje que recibe del cliente*/ printf("Mensaje: %s\n",buf_in); contador=0; /*Inicializamos contador*/ /*Vaciamos el bufer de salida*/ bzero(buf_out,sizeof(buf_out)); for(contador=0;contador
Pues lo mismo que antes pero para cada petición crea un hijo que la atiende, así se pueden atender tantas peticiones a la vez como procesos hijo (memoria disponible) se puedan crear.
/********************************/
/* SERVIDOR CONCURRENTE */
/********************************/
#include
#include
#include
#include
#include
#include "service.h"
#define TRUE 1 /*Definición de constantes*/
main () /*Programa Principal*/
{ /* Definición de variables*/
char buf_in[1024];
char buf_out[1024];
int rval,caracter,caracter0;
int i,contador;
int sock,length;
struct sockaddr_in server ;
int msgsock;
/*Creación del socket de escucha*/
sock=socket(AF_INET,SOCK_STREAM,0);
if(sock<0){ /*Si tenemos un error, lo muestra en pantalla*/ /*y sale del programa*/ fprintf(stderr,"Abriendo un socket de tipo stream. \n"); exit(1); } server.sin_family= AF_INET; /*Familia de protocolo AF_INET*/ server.sin_addr.s_addr=inet_network("127.0.0.1"); /*Dirección*/ server.sin_addr.s_addr=inet_addr("127.0.0.1"); /* del servidor*/ server.sin_port=htons(1999); /*Puerto fijo (nº1999)*/ if(bind(sock,&server,sizeof(server)) ){ /*Asociamos el socket a la dirección del servidor*/ fprintf(stderr,"Nombrando al socket de tipo stream.\n"); /*Si nos da un error, lo mostramos en pantalla y salimos del programa*/ exit(1); } length=sizeof(server); /*longitud de la dirección del servidor*/ /*Función que averigua el nº de puerto que ha asignado el sistema operativo, en el caso de que se le pida a éste que asigne un puerto automáticamente*/ /* if(getsockname(sock,&server,&length)) { fprintf(stderr,"Obteniendo el puerto para el socket"); exit(1);}*/ printf("El socket tiene el puerto %d\n", ntohs(server.sin_port)); /*Nos quedamos a la escucha con una cola para 5 clientes*/ listen(sock,5); do { /*Repite el bucle infinítamente*/ /*Aceptamos la petición de conexión del cliente...*/ msgsock=accept(sock,0,0); /*...y creamos el socket de servicio*/ /*Si ha habido un fallo en la aceptación de conexión...*/ if(msgsock==-1) /*...imprime el error por pantalla*/ fprintf(stderr,"Fallo en la función accept.\n"); else{ /*Creación de un proceso hijo*/ if(fork()==0){ /*Si no hay error al crear el proceso hijo*/ /*El proceso de servicio ya no usa el socket de escucha*/ close(sock); /*Paso la petición del cliente al proceso hijo*/ service(msgsock,&server,length); exit(0);} /*El proceso padre ya no usa el socket de servicio*/ close(msgsock);} }while(TRUE); /*Bucle infinito*/ } ************************************************* 4º -> Librería con funciones para el servidor concurrente (está hecha sólo por ver como se hacian y trataban librerías en C, realmente no hace falta pero queda bonito ;-)))))
/************************************************/
/* LIBRERÍA DEL SERVIDOR CONCURRENTE */
/************************************************/
#ifndef _SERVICE_H /*Veo si no está definida mi función, y...*/
#define _SERVICE_H /*...si no está la defino*/
#include
#include
#include
#include
#include
/*Defino las funciones que voy a usar*/
void service(int socket_hijo,struct sockaddr_in *adr,int lgadr);
#endif
/*Función de encriptación*/
void service(int socket_hijo,struct sockaddr_in *adr,int lgadr)
{
/*Definición de variables*/
char buf_in[1024];
char buf_out[1024];
int contador,rval,caracter,caracter0;
/*Mientras que el cliente no nos haga una petición de desconexión*/
do
bzero(buf_in,sizeof(buf_in)); /*Vacío el búfer de entrada*/
/*Leo mensaje del cliente*/
if((rval=read(socket_hijo,buf_in,sizeof(buf_in)))<0) /*Si ha habido un error, lo imprimo en pantalla*/ perror("ERROR: Leyendo el mensaje.\n"); if(rval==0) /*Si recibo una petición de desconexión...*/ /*Imprimo que he finalizado la conexión*/ printf("Finalizando la conexion.\n"); else printf("Mensaje: %s\n",buf_in); /*si no, imprimo el mensaje*/ contador=0; /*Inicializo el contador*/ bzero(buf_out,sizeof(buf_out)); /*Vacío el búfer de salida*/ for(contador=0;contador<=sizeof(buf_in);contador=contador+2) { /*Algoritmo de encriptación*/ caracter0=buf_in[contador]; caracter=buf_in[contador+1]; /*Si la palabra es impar no cambia el último carácter*/ if(caracter!=0) {buf_out[contador]=caracter; buf_out[contador+1]=caracter0;} else buf_out[contador]=caracter0;} /*Envío respuesta al cliente*/ if(send(socket_hijo,buf_out,strlen(buf_out),0)<0) /*Si falla, lo muestro*/ fprintf(stderr,"Fallo en la funcion Send.\n"); /*Mientras que el cliente no nos haga una petición de desconexión*/ }while (rval !=0); close(socket_hijo); /*Cerramos el socket hijo*/ }; /*Fin de la librería*/ *********************************************** 5º -> Cliente SMTP. Sencillito cliente para enviar mensajes de correo. Es como automatizar el proceso de hacerlo por telnet.
/************************/
/* CLIENTE SMTP */
/************************/
#include
#include
#include
#include
#include
#include
#include
#include
/*Definimos las constantes a utilizar*/
#define AUXILIAR "RCPT TO:"
#define REMITE "MAIL FROM:"
#define HOLA "HELO UPV.es\n"
#define CUERPO "DATA\n"
#define crlf "\n"
#define FIN "QUIT\n"
#define PUNTO ".\n"
#define SI "s"
/*Programa Principal*/
void main(void)
{
struct sockaddr_in direccion; /*Definimos las variables*/
int i,s,contador,length,longitud;
char fin[5];
int puerto;
char aux[250];
char aux1[250] = "RCPT TO:";
char respuesta[254];
char mensaje[1024];
char repeticion[50];
char DATA[250];
char datos[250];
bzero((char*)&direccion,sizeof(direccion)); /*Vacía dirección*/
/*Imprime cartel en pantalla*/
printf("_______________________________________\n");
printf(" \n");
printf(" CLIENTE SMTP \n");
printf("_______________________________________\n");
printf(" \n");
/**DIR SERVIDOR**/
/*Dirección del servidor SMTP*/
direccion.sin_addr.s_addr=inet_network("158.42.2.4");
direccion.sin_addr.s_addr=inet_addr("158.42.2.4");
direccion.sin_family=AF_INET; /*Familia de protocolo AF_INET*/
direccion.sin_port=htons(25); /*Puerto SMTP nº25*/
s=socket(AF_INET,SOCK_STREAM,0); /*Creación del socket*/
if(s<0) /*Si ha habido un error...*/ { /*...se imprime en pantalla*/ printf("ERROR al crear el socket\n"); } printf("\n"); /*Intentamos conectar con el servidor*/ if(connect(s,(struct sockaddr*)&direccion,sizeof(direccion))<0) { /*Si hay error, se imprime en pantalla y sale del programa*/ printf("ERROR AL CONECTAR \n"); exit(1); } else /*si no ha habido error...*/ { printf("Servidor (connect):\n"); /*Imprime en pantalla*/ bzero(&datos,sizeof(datos)); read(s,datos,sizeof(datos)); /*Lee los datos del servidor*/ longitud=sizeof(datos); /*Calcula longitud de los datos*/ /*Imprime los datos en pantalla*/ for(i=0;i<=250;i++){datos[i]=0;} /*Vacía cadena datos*/ for(i=0;i
/************************/
/* CLIENTE POP3 */
/************************/
#include
#include
#include
#include
#include
#include
#include
#include
#define USUARIO "USER " /*Definimos las constantes*/
#define PASSWORD "PASS "
#define LISTADO "STAT\n"
#define LEER "RETR "
#define BORRAR "DELE "
#define CRLF "\n"
#define FIN "QUIT\n"
#define PUNTO ".\n"
#define SI "s"
#define MENOS "-"
#define BIEN "Todo va Bien!!!"
#define MAL "error del servidor"
void main(void) /*Programa principal*/
{
/*Definimos las variables a utilizar*/
struct sockaddr_in direccion;
int i,j,s,contador,length,longitud;
char fin[5];
int puerto;
char aux[250];
char respuesta[254];
char mensaje[1024];
char repeticion[50];
char DATA[250];
char error[30];
char msge[2000];
char datos[250];
/*Vacía la cadena dirección*/
bzero((char*)&direccion,sizeof(direccion));
/*Imprime en pantalla*/
printf("_______________________________________\n");
printf(" \n");
printf(" CLIENTE POP3 \n");
printf("_______________________________________\n");
printf(" \n");
/**DIRECCIÓN DEL SERVIDOR**/
direccion.sin_addr.s_addr=inet_network("158.42.2.4");
/*Dirección del servidor POP3*/
direccion.sin_addr.s_addr=inet_addr("158.42.2.4");
direccion.sin_family=AF_INET; /*Familia de protocolo AF_INET*/
direccion.sin_port=htons(110); /*Puerto POP3 (110)*/
s=socket(AF_INET,SOCK_STREAM,0); /*Creamos el socket*/
if(s<0) /*Si el identificador de socket es negativo...*/
{
printf("ERROR al crear el socket\n"); /*...ha habido un error*/
}
printf("\n");
/*Establecemos la conexión y si nos devuelve un entero negativo...*/
if(connect(s,(struct sockaddr*)&direccion,sizeof(direccion))<0)
{
printf("ERROR AL CONECTAR \n"); /*...ha habido un error...*/
exit(1); /*...y salimos del programa*/
}
else /*Si la conexión ha tenido éxito...*/
{
printf("Servidor (connect):\n"); /*Imprime en pantalla*/
/*Leemos los datos que envia el servidor*/
read(s,datos,sizeof(datos));
longitud=strlen(datos); /*Longitud de la cadena datos*/
/*Imprime en pantalla la cadena datos (respuesta del servidor)*/
for(i=0;i
for(i=0;i<=250;i++){datos[i]=0;} /*Vaciamos la cadena datos*/
printf("\n");
}
/*Repetimos el siguiente bucle hasta que no haya error en el login o en el password*/
do{
printf("Introduzca su Login: "); /*Pedimos el Login*/
gets(respuesta); /*Almacenamos login en respuesta*/
bzero(aux,sizeof(aux)); /*Vaciamos la cadena aux*/
/*Concatenamos USUARIO(USER) con aux;aux=aux+USER */
strcat(aux,USUARIO);
/*Concatenamos aux con los datos del login "USER datos"*/
strcat(aux,respuesta);
/*Concatenamos "USER datos" con un retorno de carro(\n) para que el servidor nos reconozca los comandos*/
strcat(aux,CRLF);
/*Enviamos el resultado de las concatenaciones "USER datos\n"*/
if(send(s,aux,strlen(aux),0)<0)
{
/*Si no tiene éxito en enviar, imprime el error*/
printf("ERROR AL ENVIAR \n");
}
else /*Si envía bien...*/
{
printf("Servidor (USER):\n");/*Imprime en pantalla*/
read(s,datos,sizeof(datos)); /*Leemos los datos del servidor*/
longitud=sizeof(datos); /*Calculamos longitud de los datos*/
/*Imprime en pantalla la cadena datos (respuesta del servidor)*/
for(i=0;i
for(i=0;i<=250;i++){datos[i]=0;} /*Vaciamos la cadena datos*/
bzero(respuesta,sizeof(respuesta)); /*Vaciamos respuesta*/
printf("\n");
}
printf(" Introduzca su Password: "); /*Pedimos la contraseña*/
gets(respuesta); /*Almacenamos la contraseña en respuesta*/
bzero(aux,sizeof(aux)); /*Vaciamos la cadena aux*/
strcat(aux,PASSWORD); /*Concatenamos PASSWORD(PASS) con aux*/
strcat(aux,respuesta); /*Concatenamos aux
con los datos introducidos "PASS datos"*/
/*Concatenamos "PASS datos" con un retorno de carro(\n) para que el servidor nos reconozca los comandos*/
strcat(aux,CRLF);
/*Enviamos los datos "PASS datos\n" al servidor*/
if(send(s,aux,strlen(aux),0)<0)
{
printf("ERROR AL ENVIAR \n");
}
else
{
printf("Servidor (PASSWORD):\n");
read(s,datos,sizeof(datos)); /*Leemos los datos del servidor*/
longitud=sizeof(datos);
for(i=0;i
bzero(error,sizeof(error)); /*Reseteamos la cadena error*/
/*El carácter error es igual al primer carácter de la cadena datos*/
error[0]=datos[0];
/*Si la primera letra de la respuesta del servidor es '-' vuelve a preguntar login, ya que el servidor nos habra devuelto un -ERR*/
if(strcmp(error,MENOS)==0){strcpy(error,MAL);}
for(i=0;i<=250;i++){datos[i]=0;} /*Vaciamos la cadena datos*/
/*Vaciamos la cadena respuesta*/
bzero(respuesta,sizeof(respuesta));
printf("\n");
}
/*Si ha habido un -ERR, vuelve a repetir el bucle desde Login*/
}while(strcmp(error,MAL)==0);
/*Enviamos un listado (STAT) al servidor para que nos diga los mensajes que tenemos*/
if(send(s,LISTADO,5,0)<0)
{
printf("ERROR AL ENVIAR \n");
}
else /*Si no ha habido error al enviar los datos...*/
{
printf("Servidor (STAT): ");
/*Leemos la respuesta del servidor*/
read(s,datos,sizeof(datos));
/*Calculamos la longitud de la cadena datos*/
longitud=strlen(datos);
for(i=0;i
for(i=0;i<=250;i++){datos[i]=0;}
printf("\n");
}
do{ /*Repetimos el bucle mientras queramos leer más mensajes*/
printf("Introduzca el numero de mensaje a leer: ('INTRO' para
no leer ninguno)\n");
gets(respuesta); /*Obtenemos el número del mensaje a leer*/
bzero(aux,sizeof(aux)); /*Reseteamos la cadena aux*/
strcat(aux,LEER); /*Metemos leer (RETR) en la cadena aux*/
strcat(aux,respuesta); /*Concatenamos la respuesta obtenida
al aux "RETR respuesta"*/
/*Ponemos un retorno de carro (\n) al final de aux*/
strcat(aux,CRLF);
/*Reseteamos la cadena respuesta*/
bzero(respuesta,sizeof(respuesta));
/*Enviamos "RETR respuesta\n" al servidor*/
if(send(s,aux,strlen(aux),0)<0)
{
printf("ERROR AL ENVIAR \n");
}
else /*Sino ha habido error al enviar...*/
{
printf("Servidor (RETR:):\n ");
/*Leemos la respuesta del servidor*/
read(s,msge,sizeof(msge));
longitud=strlen(msge);
/*y la imprimimos*/
for(i=0;i
for(i=0;i<=250;i++){msge[i]=0;}
printf("\n");
}
printf("¨Quiere leer mas mensajes? (s/n) ");
gets(repeticion); /*Leemos la respuesta*/
/*Si la respuesta es "s" repetimos el bucle*/
}while(strcmp(SI,repeticion)==0);
do{ /*Repetimos el bucle mientras queramos borrar más mensajes*/
printf("Introduzca el n£mero de mensaje a borrar: ('INTRO' para no borrar ninguno)\n");
gets(respuesta); /*Lo siguiente es análogo al bucle anterior*/
bzero(aux,sizeof(aux));
strcat(aux,BORRAR);
strcat(aux,respuesta);
strcat(aux,CRLF);
bzero(respuesta,sizeof(respuesta));
/*Aquí enviamos "DELE respuesta\n"*/
if(send(s,aux,strlen(aux),0)<0)
{
printf("ERROR AL ENVIAR \n");
}
else
{
printf("Servidor (DELE):\n ");
/*Leemos respuesta del servidor*/
read(s,datos,sizeof(datos));
longitud=sizeof(datos);
for(i=0;i
for(i=0;i<=250;i++){datos[i]=0;}
printf("\n");
}
printf("Quiere borrar más mensajes? (s/n) ");
gets(repeticion);
/*Si la respuesta es "s" repetimos el bucle*/
}while(strcmp(SI,repeticion)==0);
/*Enviamos la desconexión (QUIT) al servidor*/
if(send(s,FIN,5,0)<0)
{
printf("ERROR AL ENVIAR \n");
}
else
{
printf("Servidor (CIERRA CONEXION): ");
/*Leemos la respuesta del servidor*/
read(s,datos,sizeof(datos));
longitud=sizeof(datos);
for(i=0;i
for(i=0;i<=250;i++){datos[i]=0;}
printf("\n");
}
} /*Fin del programa*/
************************************************