Generalidades
Host Name (nombre de la máquina)
Nombre del host v/s dirección (mateo.elo.utfsm.cl v/s 200.1.17.4)Dirección del Host (dirección de la máquina)
Obtención del nombre del hostint gethostname(char *name, int len);Esta función pone el nombre del host local en el arreglo name, el cual es de largo len. Retorna 0 en caso de éxito y -1 en falla.
Dirección única en la Internet y de 32 bits. Otros nombres: dirección de red, dirección Internet.Transformación entre nombre y dirección de máquina
Usamos notación punto para referirnos a ellas. i.e. 123.45.67.89 a cambio de 0x7B2D4359
Cada dirección de red tiene dos partes: un número de red y uno de host.
El número de host puede ser dividido en número de subred y número de host. La dirección de red es usada por los routers para el enrutamiento de los paquetes en la red.
Clase B y C no resultaron adecuadas para los tamaños típicos de las organizaciones. Clase C (254 máquinas) no logra satisfacer las necesidades de muchas empresas medianas, y Clase B resulta muy grande para éstas (65.534 máquinas).
Las normas aprobadas para modificar la definición del espacio de direcciones se conocen bajo el nombre de Classless Inter-Domain Routing (CIDR) (Enrutamiento entre dominios sin usar clases), y las normas que lo describen son: RFC 1467, RFC 1518, y RFC 1519.
Para hacer un mejor uso de las direcciones dentro de cada clase es posible definir subredes. Es decir, una clase se divide en varias subclases. Por ejemplo la red ELO tiene:
Clase C: 200.1.17.0 y la divide en dos subredes de 128 direcciones cada una.
Clase C: 200.1.28.0 de esta clase sólo tiene disponibles las subredes 200.1.28.0/26 y 200.1.28.128/26
Por otra parte la posibilidad de crear subredes aumenta en forma considerable la cantidad de entradas en las tablas de ruteo de los routers. Por ello se defines las super-redes. La idea es compactar a sólo una entrada en la tabla de ruta a todas las redes o subredes adyacentes que deban ser ruteadas hacia un mismo destino.
Caso red Electrónica años atrás.
#include <sys/types.h>Estas funciones buscan los nombres de máquinas y sus direcciones en bases de datos que dependen de la configuración del sistema.
#include <sys/socket.h>
#include <netdb.h>
#include <netinet./in.h>
struct hostent * gethostent (void)
struct hostent * gethostbyname(const char *name);
struct hostent * gethostbyaddr(const char * addr, int len, int type);
int sethostent(int stayopen);
int endhostent(void);
sethostent() y endhostent() permiten abrir y cerrar la base de datos.Estas funciones retornan un puntero a la estructura con la información sobre la máquina. Si no está retornan un NULL.gethostent() lee la próxima entrada en la base de datos.
gethostbyname busca la entrada con el nombre de máquina dado.
gethostbyaddr busca la entrada con la dirección de máquina dada.
struct hostent {Servicios y Números de Puertas
char *h_name; /* nombre oficial */
char **h_aliases; /* aliases */
int h_addrtype;
int h_length;
char **h_addr_list;
}
Orden de los Bytes en la Red
Intel (80x86, Pentium y otros) y
Digital Equipment Corporation (DEC) son little-endian. Motorola y Sun
SPARC son big-endian (byte más significativo en la
dirección menor de memoria). Solución: se definió
un orden de bytes de red (= big-endian). Así se asegura que el
tráfico puede ser leído en ambas arquitecturas.
Funciones para hacer las conversiones:
#include <sys/types.h>gethostby* retornan enteros con orden de red.
#include <netinet/in.h>
u_long htonl (u_long hostlong);
u_short htons(u_short hostshort);
u_long ntohl(u_long netlong);
u_long ntohs(u_short netshort);
Ver páginas man en plataforma específica. Por ejemplo en aragorn año 2008, se tiene:
#include <netinet/in.h>
uint32_t htonl(uint32_t hostlong);
uint16_t htons(uint16_t hostshort);
uint32_t ntohl(uint32_t netlong);
uint16_t ntohs(uint16_t netshort);
Protocolos
Relevantes en Internet
(Las imágenes de esta sección
fueron tomadas de: TCP/IP Illustrated, Volume 1. W. Richard Stevens)
Creación de
Sockets
El socket es la abstracción
usada para definir un punto de comunicación.
#include <sys/types.h>domain especifica la familia de direcciones en que se debe interpretar la dirección del socket. Puede ser: AF_UNIX , en cuyo caso la dirección es un pathname; o AF_INET , en caso de una dirección Internet IPv4, Usar AP_INET6 para IPv6. Ver más en man socket.
#include <sys/socket.h>
int socket (int domain, int type, int protocol);
type puede ser SOCK_STREAM, lo cual especifica una conexión de circuito virtual. Es bidireccional y contínuo. En la Internet éste implica TCP. Otra opción es SOCK_DGRAM, lo cual especifica envío de paquetes discretos. En la Internet éste corresponde a UDP. Otras opciones son: SOCK_RAW para acceso a un protocolo "crudo", por ejemplo directo a IP , SOCK_RDM provee servicio garantizado pero sin comprometer orden.
protocolo es el número del protocolo específico a utilizar de tipo señalado. Normalmente sólo un protocolo es soportado de un tipo dado dentro de una familia de protocolos. Lo mejor es dejarlo en cero y el sistema resuelve el valor que corresponde aese protocolo según el valor dado en type.
La función retorna un descriptor de socket. Éste es similar a un descriptor de archivo.
Funciones del lado del
Servidor
El servidor debe asociar el socket con una puerta y
dirección para que los clientes puedan acceder a él. Esto
se logra con la función bind.
#include <sys/types.h>s es el socket ya creado,
#include <sys/socket.h>
int bind (int s, const sockaddr * name, int addrlen);
struct socketaddr_in {Las máquinas pueden tener más de una tarjeta de red; i.e. más de una dirección Internet, por ello se debe especificar la dirección sin_addr. Si queremos atender requerimientos entrando por cualquier interfaz, se puede usar INADDR_ANY como dirección asociada a la puerta.
short sin_family; /* AF_INET */
u_short sin_port; /* puerta de servicio */
struct in_addr sin_addr; /* dirección asociada a la puerta */
}
Esperando por Conexiones
Sólo es requerido cuando el servicio es
orientado al stream (TCP).
#include <sys/types.h>Esta función comunica al sistema operativo que el socket está listo para recibir conexiones. backlog especifica el máximo número de requerimientos de conexión que pueden estar pendientes en cada momento (<= 5). Si hay muchos tratando de conectarse, el cliente recibe un mensaje "connection refused".
#include <sys/socket.h>
int listen (int s, int backlog);
Aceptación de Conexiones
#include <sys/types.h>Esta función retorna un nuevo descriptor de socket que el servidor usa para comunicarse con el cliente que fue aceptado. El OS almacena la información del cliente en name y el largo de la estructura en addrlen; es decir son valores de salida.
#include <sys/socket.h>
int accept (int s, struct sockaddr *name, int *addrlen);
Funciones Usadas por el
lado Cliente
Conexión con el
servidor
#include <sys/types.h>Esta función conecta el socket s con el servidor corriendo en la máquina y puerta especificada en name.
#include <sys/socket.h>
int connect (int s, struct socketaddr *name, int addrlen);
Esta fucnión puede ser usada en conexiones datagramas o de circuito virtual. En el primer caso esta función deja claro que los próximos datagramas están dirigidos al destido donde se hace la conexión. De otra forma la dirección destino debe ser especificada en cada llamado de envío de datagrama.
Funciones para Transferencia de Datos
#include <sys/types.h>Son idénticas a read and write, sólo que ellas tienen un cuarto argumento para especificar como enviar o recibir los datos.
#include <sys/socket.h>
int recv (int s, char * buf, int len, int flags);
int send (int s, const char * buf, int len, int flags);
Cuando se usa conexión datagrama, el servidor no llama a las funciones listen y accept, y el cliente generalemnet no llama a la función connect. En estos casos se usan las funciones:
int recvfrom(int s, char * buf, int len, int flags, struct sockaddr *from, int fromlen);Destrucción o Cierre del Canal de Comunicación
int sendto(int s, const char *buf, int len, int flags, struct sockaddr *to, int tolen);
#include <sys/types.h>how = 0 se cierra para lectura, se puede seguir enviando.
#include <sys/socket.h>
int shutdown(int s, int how);
Ejemplos:
TCP: Servidor
Cliente
UDP: Servidor
Cliente