Sunteți pe pagina 1din 11

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 koo, 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 ensearnos 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 comunicacin por el cual un proceso puede emitir o recibir informacin 2. Es una interfaz con la entre capa de aplicacin y el de transporte. 3. En el interior de un proceso se identificar por un descriptor, parecido al usado para la identificacin 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-

TURORIAL DE SOCKETS EN WINDOWS


By BeRtI para el foro de elhacker.net

2.Codifikacion de las seales(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 comunicacin 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 peticin Servidor: realiza el servicio

Cliente(x+1): Cierra el socket(desconecta del servidor)

Aqu os pondre el algoritmo de cmo se crea un cliente, ke sirve para todos los tipos de servidores, es decir tanto iterativos como concurrentes: Se encuentra la direccin IP y el nmero 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 mquina local y permite que TCP seleccione uno Se conecta el socket con el servidor Se comunica con el servidor, usando el protocolo de aplicacin definido para ese programa, bsicamente, consistir en el envo y recepcin de un cjto. de mensajes Se cierra la conexin

-2-

TURORIAL DE SOCKETS EN WINDOWS


By BeRtI para el foro de elhacker.net

A continuacin 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 peticin de conexin por el socket, llamando a accept y obtiene un nuevo socket para la conexin 5. Repite a. Lee una peticin del cliente b. Formula respuesta c. Enva la respuesta al cliente segn el protocolo de aplicacin 6. Cuando termina de servir a un cliente cierra la conexin 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 tamao 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-

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 parmetros 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-

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 fcilmente, 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 librera de los sockets de Windows y ya est.

-5-

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 servidor\n); 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 cdigo 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-

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: %s\n,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 conexin, 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 despus del main hay ke poner este codigo:

-7-

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 conexin, 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 librera Open Source ke simplifica el manejo de procesos en Windows, la verdad eske la librera 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 seales, mutex, comunicacin de procesos. La librera 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 explicacin de las funciones ke usaremos de esta librera: 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-

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 conexin*/ { if(procesos[i]==0) cont=i;break; } -9-

TURORIAL DE SOCKETS EN WINDOWS


By BeRtI para el foro de elhacker.net

if(cont!=-1){ /*Aceptamos la peticin de conexin del cliente... si cont encontro un hueco para crear otro proceso/* if(msgsock=accept(sock,0,0),<0){;//almacenamos el descriptor de la conexin bajo sock en //msgsock printf(error aceptando conexin..);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 -

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 pekea guia como esta sobre linux, weno si eske esta os gusta ke ya me extraaria 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 fcilmente los pekeos 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 -

S-ar putea să vă placă și