C documents and settings_pc10_configuración local_datos de programa_mozilla_firefox_profiles_1idxf97h
1. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
LOS SOCKETS EN WINDOWS: APROXIMACION
Introduccion:
Bien, mucha gente en el foro de elhacker.net kiere aprender a usar sockets para
windows, la verdad sea dicha en inet hay info pero no me mola como está, por lo menos
la ke yo he encontrado para C, asike he investigado y todo hay ke decirlo, he aprendido
bastante en unos dias... ( antes no tenia ni zorra de sockets, weno sin contar “sokets” en
vb XD). Pues ahora sintetizo lo ke he logrado aprender por mi kuenta para ke por lo
menos os sirva al menos como introduccion a los sockets en C bajo Win.
Partire de la base de ke kien lea esto sabe por lo menos un nivel medio de C, ( bastará
con saber tratar punteros y estructuras... eso es lo uniko un pokitin mas complejo ke
veremos aki, lo demas son 3 chorradas ke kualkiera sabe de C).
Tambien asumire ke sabeis un par de nociones sobre redes, es decir, ke es un puerto,
saber ke existen diferentes protocolos como tcp/ip/udp/ etc.
Y weno, basikamente es eso, este es mi primer “tutorial”, en principio pense
simplemente en resumir de una forma mas o menos entendible por mi enfermiza mente
los konocimientos adkiridos en estos dias ke he estado leyendo sobre sockets y
programandoles bajo C.... y al final pense: weno ke koño, ya ke lo voy a escribir lo
kuelgo en el foro de elhacker.net y asi aporto algo, ya ke de el he aprendido un
montonazo de cosas interesantes....
Ahora te estaras preguntando y ke narices va a enseñarnos este panolis sobre
sockets?.Pues bien, este “tuto” sera una iniciaciacion al mundo de los sockets, despues
de el tendras ke investigar, leer bastante y sobretodo programar, pero tendras “cierta
base ya”, por lo menos eso, ke sirva como aproximacion, lo mismo ke me ha servido a
mi :D.
Pd: si, mi teklado tiene tildes, y no soy dislexiko, pero me akostumbre hace mil a
eskribir asi (solo por inet no en plan serio ehhh, ke no estoy tan loko XD) ke eres libre
de korregir las faltas y/o erratas. XDD.
QUE SON LOS SOCKETS
Vale, empezamos, supongo ke ya lo sabras, pero en resumidas kuentas un socket es
esto:
1. Punto de comunicación por el cual un proceso puede emitir o recibir
información
2. Es una interfaz con la entre capa de aplicación y el de transporte.
3. En el interior de un proceso se identificará por un descriptor, parecido al usado
para la identificación de archivos.
4. Dados dos procesos ke se komunikan atraves de sockets, te puedes despreocupar
generalmente de:
1.Canal fisiko de komunikacion (capa fisika del modelo OSI)
-1-
2. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
2.Codifikacion de las señales(capa de enlace de OSI)
3.Routers o nodos de red por donde tiene ke pasar ( capa red del OSI)
4.Crear los paketes y buskar la ruta ke tienen ke seguir ( capa de trasporte del OSI)
TIPOS DE COMUNICACION CON SOCKETS
Aunque existen bastantes mas, lo mas normal es lo ke veremos en este tutorial, es decir,
dos tipos de comunicación sobre sockets tcp:
Servidor serial o iterativo: acepta un cliente cada vez.
Servidor concurrente: acepta varios clientes a la vez.
1: Servidor atiende 1 peticion de 1 cliente cada vez para un valor inicial de x=0
Servidor:
abre su puerto
espera por peticiones del cliente
Cliente(x+1):
abre su puerto
escribe su petición
Servidor:
realiza el servicio
Cliente(x+1):
Cierra el socket(desconecta del
servidor)
Aquí os pondre el algoritmo de cómo se crea un cliente, ke sirve para todos los tipos de
servidores, es decir tanto iterativos como concurrentes:
Se encuentra la dirección IP y el número de puerto del protocolo del
servidor con el que se desea comunicar
Se crea un socket
Se especifica que el programa cliente necesita un puerto de protocolo sin
usar en la máquina local y permite que TCP seleccione uno
Se conecta el socket con el servidor
Se comunica con el servidor, usando el protocolo de aplicación definido
para ese programa, básicamente, consistirá en el envío y recepción de un
cjto. de mensajes
Se cierra la conexión
-2-
3. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
A continuación os pongo el algoritmo del servidor tcp serial o iterativo:
1. Se crea un socket
2. Realiza la ligadura entre el socket y el puerto mediante bind
3. Pone el socket en modo pasivo haciendo que esté preparado para que el servidor
lo utilice mediante listen
4. Acepta una nueva petición de conexión por el socket, llamando a accept y
obtiene un nuevo socket para la conexión
5. Repite
a. Lee una petición del cliente
b. Formula respuesta
c. Envía la respuesta al cliente según el protocolo de aplicación
6. Cuando termina de servir a un cliente cierra la conexión y vuelve al paso 3
Bien, ahora pasaremos a ver codigo en C, empezaremos viendo las funciones y
estructuras ke usaremos:
Existen varios tipos de familias de sockets, como son UNIX,INTERNET,SOLARIS,
ETC ETC. Nosotros usaremos tcp asique seran de tipo Internet, por eso siempre
tendremos ke usar esta estructura:
Internet domain addres
struct sockaddr_in {
short sin_family; //familia, sera AF_INET
u_short sin_port;//puerto
struct in_addr sin_addr;//Direccion ip
char sin_zero;//relleno para manetener el tamaño original
}
La funcion para crear un socket es la siguiente:
int socket(familia, tipo, protocolo)
int familia
familia de direcciones:
AF_UNIX protocolos internos UNIX
AF_INET protocolo de Internet //esta es la ke usaremos para TCP
AF_NS protocolo de la XEROX NS
AF_IMPLIK IMP link layer (interface Multiple Layer)
int tipo
tipo de socket:
SOCKET_STREAM socket tipo stream //sockets “normales”, son los ke usaremo
SOCKET_DGRAM socket tipo datagrama // sockets para udp
SOCKET_RAW socket tipo raw//sockets puros
int protocolo
tipo de protocolo a utilizar
0: el sistema elige su protocolo
-3-
4. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
La funcion socket devuelve un entero, parecido a cuando abrimos un archivo, si hay un
error al crear el socket devuelve <0.
int bind(int sockfd, struct sockaddr *my_addr, int addrlen)
La function bind asocia el socket creado con la function socket (se usa en el servidor)
con un puerto del sistema, devuelve -1 en caso de error
Int sockfd: el identificador de socket obtenido con socket()
Struct sockaddr: puntero a la estructura vista antes, donde estaran los datos
Int addrlen: es la longitud de la estructura, basta con asignarle sizeof(struct sockaddr)
int listen(int sockfd, int backlog);
La function listen es simple, lo ke hace es poner a la escucha el socket (evidente, solo se
usa en el servidor), una vez creado este y bindeado.
Sockfd es el descriptor del socket
Backlog: es la cola, es decir, si pones 3, kuando se konecte un cliente, y lleguen otros 2,
esos 2 clientes estaran esperando a ke llegue su turno en una cola gestionada por el
OS.
Devuelve -1 si hay un error.
int accept(int sockfd, void *addr, int *addrlen);
Cuando llega una peticion de un cliente para conectar con el servidor a un puerto
concreto, como dije antes se pone en la cola, y cuando le toca el turno con la function
accept, aceptas la connexion y asi es como se establece, devuelve -1 si hay un error
Sockfd: es el descriptor del socket
Los otros dos parámetros se pueden poner a 0
int connect(int sockfd, struct sockaddr *serv_addr, int
addrlen);
Esta funcion es la ke realica la connexion desde el cliente al servidor. Es muy sencilla
de usar, devuelve -1 si hay algun error
Sockfd: nuestro descriptor de socket
Struct sockaddr: la estructura donde estan los datos del Server donde kieres conectar
Addrlen: ya lo dije antes, la longitud de la estructura, basta con poner
sizeof(estructura)
int send(int sockfd, const void *msg, int len, int flags);
Esta funcion sirve para enviar desde un extreme al otro de la connexion, informacion.
Sockfd: es nuestro descriptor de socket de siempre
*msg: una cadena de caracteres donde esta el mensaje a enviar
Len: la longitud de dicha cadena
Flags: basta con poner 0.
int recv(int sockfd, void *buf, int len, unsigned int
flags);
-4-
5. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
Esta funcion al contrario ke send, recive la informacion ke se envia con send
Send y recv devuelven los bytes enviados y recibidos en cada caso, y -1 si hubo error
Sockfd: descriptor del socket
Buf: cadena de caracteres donde almacenaremos la info ke nos llegue
Len: longitud de la cadena
Flags: 0
Existen mas funciones pero no hablare de ellas, como gethostname, getpeername. No
son indispensables y en google puedes encontralas fácilmente, son para obtener el
nombre del ekipo local y remoto…
Para cerrar un socket ke ya no vas a usar se hace asi:
Closesocket(int sockfd) donde sockfd es nuestro descriptor de socket
Ahora pondre el codigo en C de un cliente muy muy basico
Para todos los ejemplos he usado Dev c++, solo tienes ke linkear la librería de los
sockets de Windows y ya está.
-5-
6. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
#include <stdio.h>
#include <windows.h>
#include <string.h>
#define ip “127.0.0.1” //ip del servidor al ke konectar
#define puerto 69 //puerto del server
main()
{
int sock;//descriptor del socket.
int bytesenv, bytesrcv;
struct sockaddr_in *direccion; //datos del servidor al ke konectaremos
char bufer[1024]; //bufer donde guardaremos lo ke nos envie el Server.
char cadena[1024]; // la info ke enviaremos al Server.
char error[200] // aki guardaremos los posibles errores ke se produzcan..
direccion.sin_addr.s_addr=inet_addr(ip);
direccion.sin_family=AF_INET// protocolo af inet, visto antes.
direccion.sin_port=htons(puerto);//htons convierte el puerto al formato de red.
If(sock=socket(AF_INET,SOCK_STREAM,0))<0{ // obtenemos el descriptor del socket
perror(error);
printf(“%s”,error);
exit(0);
}
else
printf(“socket creado con éxito”);
//conectamos al servidor
If(connect(sock,(struct sockaddr*)&direccion,sizeof(direccion))<0){
printf(“error conectando…”);
exit(0);}
if(bytesrecv=recv(sock,buffer,sizeof(buffer),0)==-1){
printf(“Error recibiendo msg, saliendo…”);exit(0);}
printf(“conectado al servidorn”);
printf(“Mensagje a enviar: “);
gets(cadena);
if(bytesenv=send(sock,cadena,strlen(cadena),0)==-1){
printf(“error enviando msg, cerrando…”);exit(0);}
printf(“nMensage enviado. Esperando respuesta…”);
printf(“Mensaje recibido: %s”,buffer);
}
Una cosa, ese código es lo mas simple, imaginate ke en lugar de un mensaje , kieres
recibir mas, o infinitos del servidor, puedes hacer un while(1) // bucle infinito, y cada
vez recibir un msg, y pedir una cadena por teclado y enviarla, asi seria un Chat x
ejemplo xD.
Ahora si, aki va el codigo del Server serial
-6-
7. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
#include <stdio.h>
#include <winsock.h>
#include <string.h>
#define puerto 69
main(){
//variables
int bytesrecv,bytesenv,sock,conectado;
char buffer[1024],cadena[1024],bienvenido[22]=”welcome to my server”;struct
sockaddr_in server;
if(sock=socket(AF_INET,SOCK_STREAM,0)<0){; // creamos el socket
printf(“Error creando el socket, saliendo…”);exit(0)}
server.sin_family= AF_INET; // familia socket
server.sin_addr.s_addr=inet_addr("127.0.0.1");
server.sin_port=htons(puerto); //Puerto
if(bind(sock,(struct sockaddr *)&server,sizeof(server))<0 ){//bindeamos…
printf(“error asociando socket al puerto…”);exit(0);}
listen(sock,5); // nos kedamos a la eskuxa con una cola de maximo 5 clientes
do{
if(conectado=accept(sock,0,0)<0){
printf(“error aceptando connexion”);exit(0);}
if(send(conectado,bienvenido,sizeof(bienvenido),0)<0){
printf(“error enviando msg de bienvenida”);exit(0);}
if(bytesrecv=recv(conectado,buffer,sizeof(buffer),0)==-1){
printf(“Error recibiendo msg, saliendo…”);exit(0);}
printf(“mensaje del cliente: %sn”,buffer);
memset(buffer,0,sizeof(buffer)); esta funcion vacia el buffer de entrada
closesocket(conectado); //cerramos el socket.
}while(1);
En el codigo del server tambien puedes hacer una especie de chat, modificando el bucle
infinito, la condicion del bucle seria mientras la funcion recv no devuelva 0, por ke si
devuelve 0 significa ke el cliente cerro la conexión, asi mostrarias todos los mensajes ke
lleguen, y si pones un scanf, gets o fgets para recoger un msg x teclado ya tienes el
Chat.
PD: Se me olvidaba, en Windows hay ke iniciar el winsock, asike después del main hay
ke poner este codigo:
-7-
8. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
WSADATA wsaData; // Si esto no funciona
//WSAData wsaData; // prueba esto en su lugar
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
printf(“Error iniciando Winsock, thx windows xD");exit(1);}
Ahora veremos como hacer el servidor concurrente, es decir ke acepte varios clientes al
mismo tiempo, y se comunique con ellos a la vez tambien.
Para esto se puede hacer de varias maneras, una por ejemplo seria iterativamente que
personalmente a mi no me gusta, y otra un poco mas compleja pero ke kreo ke es mejor,
y es ke kada vez ke se conecte un cliente, creemos un proceso nuevo ke se okupe de
atender su conexión, es decir, crear un proceso nuevo por cada cliente ke llegue.
Si bien implementar en Linux esto es bastante facilito, gracias a nuestra kerida funcion
fork(), en Windows hay ke lidiar con varias funciones como createproccess/thread etc,
ke tienen un webo de argumentos y no me gustan nada.
Solucion? Sencilla, nos descargaremos una librería Open Source ke simplifica el manejo
de procesos en Windows, la verdad eske la librería en cuestion tiene mucho potencial,
pero nosotros solo usaremos 2 de sus funciones, ke seran la de crear el proceso nuevo, y
la de terminarlo xD. Aunque ya os digo ke se pueden manejar señales, mutex,
comunicación de procesos….
La librería en cuestion es esta: PTHREAD.H, aki esta la web oficial:click
Y para descargarla directamente: click
La instalacion es sencilla; descomprimimos y en la carpeta prebuilt.2, hay dos carpetas
llamadas include y lib, pues los archivos ke hay dentro de cada una , los copiamos a las
carpetas include y lib de nuestro compilador, en mi caso en el dev c++.
Breve explicación de las funciones ke usaremos de esta librería:
Necesitaras linkear el proyecto a la libpthreadGC2.a e incluir pthread.h
pthread_create (thread,attr,start_routine,arg)
Devuelve distinto de 0 si no hay error y el proceso se crea.
Thread: identificador del proceso
Attr:fija los atributos ke tendra el proceso, usaremos NULL q es por defecto
Stara_routine: funcion ke se ejecutara al comenzar el nuevo proceso
Arg: argumentos ke puedes pasar al proceso, solo se puede pasar 1, por lo ke si kieres
pasar mas tendras ke pasarle una estructura con los argumentos en ella.
Ahora veremos el codigo C de un Server concurrente ke recibe msgs de varios clientes a
la vez.
-8-
9. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
#include <stdio.h>
#include <pthread.h>
#include <windows.h>
#include <strings.h>
#define puerto 69
#define maxproc 10
void manejasockets(void *argumentos);
struct edatos{
int socketh;
int proceso;
};
Int procesos[maxproc]; // muy mal habito de prog. Siempre ke podais evitad declaracion
//de variables globales, yo aki lo hago xq me apetece xD, vostros podeis pasar este
//argumento por referencia y modificarlo en cada proceso :P
Main()
{
WSADATA wsaData;
struct edatos datos;
int proce=0,i;
pthread_t threads[proc];
int sock,length,msgsock,rc;
struct sockaddr_in server ;
for(proce=0;proce<=proc;proce++)
procesos[proce]=0;
server.sin_family= AF_INET; //Familia de protocolo AF_INET
server.sin_addr.s_addr=inet_addr("127.0.0.1");
server.sin_port=htons(puerto); //Puerto
if(sock=socket(AF_INET,SOCK_STREAM,0)<0){
printf(“error creando el socket);exit(0);}
if(bind(sock,(struct sockaddr *)&server,sizeof(server))<0 ){//bindeamos…
printf(“error asociando socket al puerto…”);exit(0);}
listen(sock,5); // nos kedamos a la eskuxa con una cola de maximo 5 clientes
do{
for(i=1;i<=proc;i++) /*”busco un hueco para crear un proceso”, xq el maximo de
procesos ke he definido es 10, entonces si hay mas de 10 procesos, es decir mas
conexiones no aceptaremos la conexión*/
{
if(procesos[i]==0)
cont=i;break;
}
-9-
10. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
if(cont!=-1){ /*Aceptamos la petición de conexión del cliente... si cont encontro un
hueco para crear otro proceso/*
if(msgsock=accept(sock,0,0),<0){;//almacenamos el descriptor de la conexión bajo
sock en //msgsock
printf(“error aceptando conexión..”);exit(0);}
else{
datos.socketh=msgsock; //descriptor para el socket ke manejara el procesohijo
datos.proceso=cont;//numero de proceso
pthread_create(&threads[cont],NULL,contar,&datos);//creamos el proceso hijo
procesos[cont]=1;
}
}
}while(1); //bucle infinito
}// fin main
Void manejarsockets(void *argumentos)
{
//obtenemos los argumentos…
struct edatos *misdatos;
misdatos=(struct edatos *) argumento;
char entrada[102400];// donde almacenaremos la info ke nos llegue.
char error[1024]; // por si se produce un error almacenarlo ahí.
int sockethijo=misdatos->socketh;
int proceso=misdatos->proceso;
int resul;
do{
memset(entrada,0,sizeof(entrada)); //entrada similar a bzero de Linux, vacia la
cadena entrada.
if((resul=recv(sockethijo,entrada,sizeof(entrada),0))<0){ // error recibiendo datos
perror(error);
printf("%s",error);}
else{
if(resul==0){ // peticion de desconexion realizada por el cliente
printf("Host remoto desconectado");}
else{
printf("nmsg:%s socket:%d",entrada,proceso);}}
}while(resul!=0); //repetir mientras no se nos pida la desconexion del cliente
closesocket(sockethijo); // cerramos el socket e indicamos ke el prcoeso ha
terminado.
procesos[proceso]=0;
}
- 10 -
11. TURORIAL DE SOCKETS EN WINDOWS
By BeRtI para el foro de elhacker.net
Vale, pues de momento esto es todo, kedan por hacer muchas cosas pero con esto
tendreis para empezar.
Aclarar ke estos sockets son blokeantes, es decir, el programa / proceso no hara nada
mas mientras se ejecute la orden accept, recv, send….
Por supuesto hay metodos para ke eso no pase, una de ellas es hacer un timeout. Si
kereis os lo explico otro dia xq es bastante sencillo.
Tambien decir ke es posible ke kon la funcion Send no envieis todos los bytes ke
keriais, por ke? Pues xq puede ke Windows se le pire la pinza y no envie toda la info
por kualkier motivo, asike tambien os explicare como aseguraros de ke enviais toda la
info ke kereis enviar al llamar a la funcion send ( sencillo de hacer tb…)
Tambien espero hacer otra pekeña guia como esta sobre linux, weno si eske esta os
gusta ke ya me extrañaria xDD, aunq sobre Linux hay mucha info por inet pero weno,
ya veremos nens.
Pues nada, esto es todo, sois libres para modificar este texto, corregir todos mis gazapos
( ke seguro ke son un weeeeebo xd) y haced lo ke kerais, solo os pido ke si lo
reproducis en mas sitios pongais mi nick como fuente :D.
PD: lo mas seguro eske los ejemplos no compilen, ya ke lo he escrito de memoria,
seguramente tendran fallos tontos komo algun “*” olvidado en algun puntero.. alguna
llave de cierre olvidada etc. Si preguntais en el foro preguntando xq no os compila algun
codigo ya os digo ke es por eso, asike esas preguntas no las respondere, xq si no soys
capaces de encontrar el error ( si eske los hay ke no lo se, no pienso buscarlos ahora xD)
no os kontestare, xq para meterse kon sockets hay ke saber un pokito de C antes, y si ya
sabes C resolveras fácilmente los pekeños fallos ke haya podido tener, y si no, eske no
tendrias ke intentar compilar esos codigos hasta tener una base mejor. Enga wen rollito
y nos vemos!
Salu2
BeRtI
- 11 -