Programacion en C/C++
Sockets en Windows - Funciones de Sockets |
Escrito por adrianvaca | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Domingo, 20 de Marzo de 2011 19:28 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Página 3 de 5
af: Dominio de comunicación (AF_INET en nuestro caso). type: Tipo de dominio (SOCK_STREAM al ser conexión TCP/IP). protocol: Protocolo de comunicación (dejaremos 0 para que se el sistema lo escoja por defecto, en este caso el sistema escogerá el protocolo TCP). Valor de retorno: La función socket devolverá un descriptor del socket, o en caso de error INVALID_SOCKET y el código de error es retornado por WSAGetLastError. Función bind Cuando se crea un socket con socket(), se crea en un espacio de nombres (familia de direcciones), pero no tiene ningún nombre asignado. bind establece la asociación local del socket asignando un nombre local al socket anónimo.
sock: Un descriptor que identifica el socket de comunicación. name: La dirección para asignar al socket. La estructura sockaddr se define como:
Excepto el campo sa_family, los demás campos de la estructura sockaddr se expresan en network byte order. namelen: Tamaño de la estructura sockaddr. Valor de retorno: La función bind devolverá 0 en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Función listen
sock: Un descriptor que identifica el socket de comunicación. backlog: La longitud máxima que la cola de conexiones pendientes puede alcanzar. Si este valor es SOMAXCONN, entonces el proveedor del servicio subyacente responsable del socket pondrá backlog a un valor máximo razonable. Valor de retorno: La función listen devolverá 0 en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Función accept
sock: Un descriptor que identifica el socket de comunicación. addr: Un puntero opcional a un buffer que recibe la dirección de la entidad que une, conocido como "capa de comunicaciones". El formato exacto del argumento addr es determinado por la familia de direcciónes establecida cuando el socket fue creado. addrlen: Un puntero opcional a un entero que contiene la longitud de la dirección addr. Valor de retorno: La función accept devolverá un descriptor de socket que será el que usaremos para enviar y recibir información con la aplicación cliente en caso se ejecutarse correctamente, en caso de error INVALID_SOCKET y el código de error es retornado por WSAGetLastError. Función connect
sock: Un descriptor que identifica el socket de comunicación. name: Zona de memoria de una estructura tipo sockaddr con los datos de conexión del cliente hacia el servidor. namelen: Tamaño de la estructura sockaddr. Valor de retorno: La función accept devolverá 0 en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Función send
sock: Un descriptor que identifica el socket de comunicación. buf: Buffer donde se encuentra el mensaje a enviar. len: Tamaño del buffer que contiene el mensaje a enviar. flags: Banderas que especifican la forma en que se enviarán los datos (por defecto 0). Otros posibles flags son: MSG_DONTROUTE: Especifica que los datos no deben estar sujetos a una ruta. Un Servidor de Sockets de Windows puede ignorar esta bandera. MSG_OOB: Envía los datos fuera de banda (solo para sockets del tipo SOCK_STREAM). Valor de retorno: La función send devolverá el número de bytes que se han enviado en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Esta función es bloqueante, es decir, hasta que se envíen los datos no se continuará con la ejecución del programa. Función recv
sock: Un descriptor que identifica el socket de comunicación. buf: Puntero a un buffer donde se almacenará el mensaje enviado. len: Tamaño del buffer que contendrá el mensaje enviado. flags: Banderas que especifican la forma en que se recibirán los datos (por defecto 0). Otros posibles flags son: MSG_PEEK: Acumula a los datos entrantes. Los datos se copian en el buffer pero no son removidos de la cola de la entrada. MSG_OOB: Proceso fuera de banda. Valor de retorno: La función recv devolverá el número de bytes que se han recibido en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Esta función es bloqueante, es decir, hasta que se reciban datos no se continuará con la ejecución del programa. Función shutdown La función shutdown desactiva el envío y/o la recepción de mensajes en un socket.
sock: Un descriptor que identifica el socket de comunicación. how: Bandera que especifica qué tipos de funcionamiento ya no se permitirán. Estas pueden ser: SD_RECEIVE: Se bloquearán los mensajes entrantes subsiguientes. Esto no tiene efecto en las capas protocolares. Para los sockets TCP, si todavía hay datos en la cola del socket en espera de ser recibidos, o llegan datos de respuestas, la conexión se restablece hasta que los datos sean entregados al usuario. Para los sockets UDP, se aceptan los datagramas entrantes que se encuentren en la cola. En ningún caso se generará un paquete de error ICMP. SD_SEND: Se bloquearán los subsiguientes mensajes enviados . Para TCP sockets, un mensaje FIN será enviado. SD_BOTH: Deshabilita tanto el envío como la recepción de mensajes subsiguientes. Valor de retorno: La función shutdown devolverá 0 caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Función sendto
sock: Un descriptor que identifica el socket de comunicación. buf: Buffer donde se encuentra el mensaje a enviar. len: Tamaño del buffer que contiene el mensaje a enviar. flags: Banderas que especifican la forma en que se enviarán los datos (por defecto 0). Otros posibles flags son: MSG_DONTROUTE: Especifica que los datos no deben estar sujetos a una ruta. Un Servidor de Sockets de Windows puede ignorar esta bandera. MSG_OOB: Envía los datos fuera de banda (solo para sockets del tipo SOCK_STREAM). to: Puntero opcional a una estructura sockaddr con la dirección del socket al que se conectará. tolen: Tamaño de la estructura ingresada en to. Valor de retorno: La función sendto devolverá el número de bytes que se han enviado en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Esta función es bloqueante, es decir, hasta que se envíen los datos no se continuará con la ejecución del programa. Función recvfrom
sock: Un descriptor que identifica el socket de comunicación. buf: Puntero a un buffer donde se almacenará el mensaje enviado. len: Tamaño del buffer que contendrá el mensaje enviado. flags: Banderas que especifican la forma en que se recibirán los datos (por defecto 0). Otros posibles flags son: MSG_PEEK: Acumula a los datos entrantes. Los datos se copian en el buffer pero no son removidos de la cola de la entrada. MSG_OOB: Proceso fuera de banda. from: Puntero opcional a un buffer en el que se almacenará la dirección de la fuente conectada. fromlen: Puntero a una variable interna donde se especifica el tamaño de la estructura pasada en from y donde se almacenará la cantidad de datos guardados. Valor de retorno: La función recvfrom devolverá el número de bytes que se han recibido en caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Esta función es bloqueante, es decir, hasta que se reciban datos no se continuará con la ejecución del programa. Función closesocket
sock: Un descriptor que identifica el socket de comunicación. Valor de retorno: La función closesocket devolverá 0 caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Nota: Todas estas funciones se hallan implementadas en la librería libwsock32.a o wsock32.lib. Otras funciones para el manejo de Sockets Función getprotobyname Retorna un puntero a una estructura la cual contiene el nombre y el número del protocolo correspondiente con el nombre ingresado.
name: Buffer donde se encuentra el nombre del protocolo.
Función getsockname Devuelve la dirección del socket.
sock: Un descriptor que identifica el socket de comunicación. name: Buffer donde se almacenará la dirección (nombre) del socket. namelen: Tamaño del buffer name. Función gethostbyaddr Obtiene información del Host a través de su dirección.
addr: Puntero a una dirección en network byte order. len: Largo de la dirección type: Tipo de dirección. Función gethostbyname Obtiene información del Host a través de su nombre.
name: Buffer que contendrá el nombre del Host. Función gethostname Obtiene información del Host Local Predeterminado.
name: Buffer donde se almacenará el nombre del Host. namelen: Tamaño del buffer. Función inet_addr Convierte una dirección IP en notación números y puntos, en un unsigned long, retorna la dirección en network byte order.
cp: Bufer que contiene la dirección IP. Retorna -1 si hubo error. Función inet_ntoa Convierte una direccion IP unsigned long en network byte order, a un string en números y puntos.
in: Estructura que representa una dirección de IP de Internet. Retorna NULL si hubo error. APIS de Windows para el manejo de sockets Función WSAStartup Inicializa la Dll encargada de los sockets de Windows.
wVersionRequested: Versión de Windows Sockets mínima necesitada. El byte de mayor orden especifica la versión menor (la revisión); el byte de menor orden especifica la versión mayor. lpWSAData: Puntero a una estructura WSADATA que recibirá los detalles de la implementación de Windows Sockets. Valor de retorno: La función WSAStartup devolverá 0 caso se ejecutarse correctamente, distinto de 0 en caso contrario. Función WSACleanup Libera la Dll encargada de los sockets de Windows.
Valor de retorno: La función WSACleanup devolverá 0 caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError. Nota: Existen implementaciones de todas las funciones de sockets sobre WSA, por ejemplo WSASocket, WSAConnect, etc. pero éstas solo agregan más opciones a la forma en que la conexión se realizará. Configurando los Sockets Modos de funcionamiento del socket: Supongamos un ejemplo, creamos un socket y nos conectamos a un servidor, sabemos que el socket nos provee una comunicación bidireccional, podemos enviar y recibir datos simultáneamente. Llamamos a la función recv() para recibir datos, pero el servidor en ese momento no tiene nada para enviarnos, entonces la función recv() no retorna. Justo en ese momento queremos enviar datos hacia el servidor, pero no podemos porque la función recv() no retornó y nos bloqueó el programa. Debemos encontrar alguna forma para que la función recv() retorne aunque el servidor no envie nada. Esto se realiza estableciendo al socket como no bloqueante. Cuando creamos un socket, se establece como bloqueante, al llamar a ciertas funciones como accept(), recv(), send(), etc, se bloquea el programa. Para establecer al socket como no bloqueante utilizamos la función ioctlsocket() de la siguiente manera :
sock: Un descriptor que identifica el socket de comunicación. cmd: Comando que se va a aplicar al socket sock. argp: Puntero a los parámetros para cmd. Comandos soportados por esta función: FIONBIO: Activa o desactiva el modo del no bloqueante del socket sock. argp apunta a un unsigned long que es distinto de cero si el modo no bloqueante será activado y a cero si será desactivado. Nota: Las funciones WSAAsyncSelect o WSAEventSelect setean automáticamente el socket en modo no bloqueante. Si se omite WSAAsyncSelect o WSAEventSelect en un socket, entonces cualquier intento de usar ioctlsocket para setear el socket en modo no bloqueante fallará y devolverá el error WSAEINVAL. Para setear un socket en modo no bloqueante, se debe desactivar WSAAsyncSelect primero llamando WSAAsyncSelect con el parámetro de lEvent igual a cero, o desactivar WSAEventSelect llamando WSAEventSelect con el parámetro lNetworkEvents igual a cero. Ejemplo:
Nota 2: Estas funciones se hallan incluidas en la librería libws2_32.a o ws2_32.lib. y requieren la versión de 2.0 de Winsocks. FIONREAD: Determine la cantidad de datos que pueden leerse atómicamente del socket sock. argp apunta a un unsigned long donde ioctlsocket guarda el resultado. Si sock es un stream orientado (por ejemplo, tipo SOCK_STREAM), FIONREAD devuelve la cantidad de datos que pueden leerse en un solo recv; esto puede o no puede ser igual a la cantidad total de datos en la cola del socket. Si sock es un mensaje orientado (por ejemplo, tipo SOCK_DGRAM), FIONREAD devuelve el tamaño de los primeros datagram (el mensaje) en la cola del socket. SIOCATMARK: Determina si se ha leído todo o parte de los datos fuera de banda. Esto sólo aplica a sockets de tipo stream (por ejemplo, tipo SOCK_STREAM) que se han configurado para la recepción en línea de cualquier dato fuera de banda (SO_OOBINLINE). Si ningún dato fuera de banda está esperando ser leído, la operación retorna TRUE. En caso contrario, retornará FALSE, y los próximos recv o recvfrom realizados en el socket recuperarán algunos o todos los datos que preceden la marca. Valor de retorno: La función ioctlsocket devolverá 0 caso se ejecutarse correctamente, en caso de error SOCKET_ERROR y el código de error es retornado por WSAGetLastError.
Una vez establecido el socket como no bloqueante, se puede llamar a la funciones bloqueantes como recv() para recibir datos, si no hay datos disponibles recv() devuelve SOCKET_ERROR y WSAGetLastError devuelve WSAEWOULDBLOCK. Se puede ir consultando (polling) el socket para saber si hay datos disponibles, pero esta no es una solución muy buena, se consume tiempo de CPU consultando al socket si tiene datos, se verá más adelante una solución más elegante. Función select Nos permite monitorear un conjunto de descriptores de sockets y nos avisa cuales tienen datos para leer, cuáles están listos para escribir, y cuáles produjeron excepciones
nfds: Se ignora y sólo incluyó por compatibilidad. readfds: Un puntero opcional a un conjunto de sockets que ejecutan lecturas. writefds: Un puntero opcional a un conjunto de sockets que ejecutan escrituras. exceptfds: Un puntero opcional a un conjunto de sockets que han cometido errores. timeout: Tiempo máximo de espera, NULL por bloquear el funcionamiento. Monitorea 3 conjuntos distintos de sockets, aquellos agregados al conjunto readfds los monitorea para ver si hay caracteres disponibles para leer, al conjunto writefds los monitorea para ver si están listos para ser escritos y al conjunto exceptfds los monitorea para ver si se producen excepciones. Se definen cuatro macros en el archivo WINSOCK2.H para manipular y verificar los conjuntos de descriptores. La constante FD_SETSIZE determina el número máximo de descriptores en un conjunto. (El valor predefinido de FD_SETSIZE es de 64 pero puede modificarse definiendo FD_SETSIZE a otro valor antes incluir WINSOCK2.H) Los macros para manipular y verificar los elementos de fd_set son: FD_CLR(SOCKET sock, fd_set *set) - Quita el descriptor sock del conjunto. FD_ISSET(SOCKET sock, fd_set *set) - Devuelve distinto de cero si sock es un miembro del conjunto. Si no, cero. FD_SET(SOCKET sock, fd_set *set) - Agrega el descriptor sock al conjunto. FD_ZERO(fd_set *set) - Inicializa el conjunto en NULO. timeout determina cuánto tiempo select puede esperar para retornar. Si timeout es NULL, select se bloqueará indefinidamente hasta por lo menos un descriptor cumpla con alguno de los criterios especificados. La otra opción es que timeout apunte a una structura timeval que especifique el tiempo máximo que select debe esperar antes de retornar. Cuando se produzca un evento el valor de timeval será alterado. Si timeval se inicializa con {0, 0}, select retornará inmediatamente. Estructura timeval:
Valor de retorno: Devuelve el número descriptores que están listos en las estructuras fd_set, 0 si expiró el límite de tiempo, o SOCKET_ERROR si ocurre un error y el código de error es retornado por WSAGetLastError. Ejemplo:
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Última actualización el Domingo, 20 de Marzo de 2011 19:33 |
Otros artículos | |
Comentarios
Primero el servidor luego el cliente
Suscripción de noticias RSS para comentarios de esta entrada.