Programaci�n B�sica de Sockets en Unix para Novatos


Tabla de contenidos
Introducci�n
Diferentes tipos de sockets en Internet
Estructuras
Conversiones
Direcciones IP
Funciones Importantes
Algunas palabras sobre dns
Un ejemplo de Servidor de Flujos
Un ejemplo de Cliente de Flujos
�ltimas Palabras

Introducci�n

�Est�s tratando de aprender programaci�n de sockets en C? �O piensas que es una tarea demasiado dif�cil? Si es as�, debes leer este tutorial b�sico para aprender las ideas y conceptos b�sicos y as�, empezar a trabajar con sockets. Tras leer este tutorial no esperes ser un “maestro” en la programaci�n de sockets. S�lo lo ser�s si practicas y lees mucho.


Diferentes tipos de sockets en Internet

En primer lugar deber� explicar qu� es un socket. De un modo muy simple, se puede decir que es una manera de hablar con otra computadora. Para ser m�s preciso, es una manera de hablar con otras computadoras usando descriptores de ficheros est�ndar de Unix. En Unix, todas las acciones de entrada y salida son desempe�adas escribiendo o leyendo en uno de estos descriptores de fichero, los cuales son simplemente un n�mero entero, asociado a un fichero abierto que puede ser una conexi�n de red, un terminal, o cualquier otra cosa[1]

Ahora bien, sobre los diferentes tipos de sockets en Internet, hay muchos tipos pero s�lo se describir�n dos de ellos - Sockets de Flujo (SOCK_STREAM) y Sockets de Datagramas (SOCK_DGRAM).

Y “�cu�l es la diferencia entre estos dos tipos?”, podr�as preguntarte. He aqu� la respuesta:

Sockets de Flujo. Est�n libres de errores: Si por ejemplo, envi�ramos por el socket de flujo tres objetos "A, B, C", llegar�n al destino en el mismo orden -- "A, B, C". Estos sockets usan TCP ("Transmission Control Protocol"[2]) y es este protocolo el que nos asegura el orden de los objetos durante la transmisi�n.

Sockets de Datagramas. �stos usan UDP (“User Datagram Protocol”[3]), y no necesitan de una conexi�n accesible como los Sockets de Flujo -- se construir� un paquete de datos con informaci�n sobre su destino y se enviar� afuera, sin necesidad de una conexi�n.

Mucho m�s podr�a explicarse aqu� sobre estas dos clases de sockets, pero creo que esto es suficiente como para captar el concepto b�sico de socket. Entender qu� es un socket y algo sobre estos dos tipos de sockets de Internet es un buen comienzo, pero lo m�s importante ser� saber c�mo trabajar con ellos. Esto se aprender� en las pr�ximas secciones.


Estructuras

El prop�sito de esta secci�n no es ense�ar el concepto de estructuras en programaci�n, sino ense�ar c�mo se usan �stas en la programaci�n de Sockets en C. Si no sabes lo que es una estructura, mi consejo es leer un buen tutorial de C. Por el momento, digamos simplemente que una estructura es un tipo de dato que es un conglomerado, o sea, que puede contener otros tipos de datos, los cuales son agrupados todos juntos en un �nico tipo definido por el programador.

Las estructuras son usadas en la programaci�n de sockets para almacenar informaci�n sobre direcciones. La primera de ellas es struct sockaddr, la cual contiene informaci�n del socket.

struct sockaddr 
{ 
   unsigned short sa_family;  /* familia de la direcci�n */ 
   char sa_data[14];          /* 14 bytes de la direcci�n del protocolo */  
}; 

    

Pero, existe otra estructura, struct sockaddr_in, la cual nos ayuda a hacer referencia a los elementos del socket.

struct sockaddr_in 
{ 
   short int sin_family;        /* Familia de la Direcci�n              */ 
   unsigned short int sin_port; /* Puerto                               */
   struct in_addr sin_addr;     /* Direcci�n de Internet                */
   unsigned char sin_zero[8];   /* Del mismo tama�o que struct sockaddr */ 
}; 
    

Nota. sin_zero puede ser configurada con ceros usando las funciones memset() o bzero() (Ver los ejemplos m�s abajo).

La siguiente estructura no es muy usada pero est� definida como una uni�n.

Como se puede ver en los dos ejemplos de abajo (ver la secci�n de nombre Un ejemplo de Servidor de Flujos y la secci�n de nombre Un ejemplo de Cliente de Flujos), cuando se declara, por ejemplo “client” para que sea del tipo sockaddr_in, luego se hace client.sin_addr = (...).

De todos modos, aqu� est� la estructura:

    
struct in_addr 
{
   unsigned   long s_addr;
};

Finalmente, creo que es mejor hablar sobre la estructura hostent. En el ejemplo de Cliente de Flujos (ver la secci�n de nombre Un ejemplo de Cliente de Flujos), se puede ver c�mo se usa esta estructura, con la cual obtenemos informaci�n del nodo remoto[4].

Aqu� se puede ver su definici�n:

    
struct hostent 
{   
   char *h_name;                   /* El nombre oficial del nodo.               */
   char **h_aliases;               /* Lista de Alias.                           */
   int h_addrtype;                 /* Tipo de direcci�n del nodo.               */
   int h_length;                   /* Longitud de la direcci�n.                 */
   char **h_addr_list;             /* Lista de direcciones del nombre del       */
                                   /* servidor.                                 */
   #define h_addr  h_addr_list[0]  /* Direcci�n, para la compatibilidad con     */
                                   /* anteriores.                               */
};

Esta estructura est� definida en el fichero netdb.h.

Al principio, es posible que estas estructuras nos confundan mucho. Sin embargo, despu�s de empezar a escribir algunas l�neas de c�digo, y tras ver los ejemplos que se incluyen en este tutorial, ser� mucho m�s f�cil entenderlas. Para ver c�mo se pueden usar estas estructuras, recomiendo ver los ejemplos de la secci�n de nombre Un ejemplo de Servidor de Flujos y la secci�n de nombre Un ejemplo de Cliente de Flujos.


Conversiones

Existen dos tipos de ordenamiento de bytes: bytes m�s significativos, y bytes menos significativos. �ste es llamado “Ordenaci�n de Bytes para Redes”[5], algunas m�quinas utilizan este tipo de ordenaci�n para guardar sus datos internamente.

Existen dos tipos a los cuales seremos capaces de convertir: short y long [6]. Imagin�monos que se quiere convertir una variable larga de Ordenaci�n de Bytes para Nodos a una de Orden de Bytes para Redes. �Qu� har�amos? Existe una funci�n llamada htonl() que har�a exactamente esta conversi�n. Las siguientes funciones son an�logas a �sta y se encargan de hacer este tipo de conversiones:

Estar�s pensando ahora para qu� necesitamos todas estas funciones, y el porqu� de estos ordenamientos. Bien, cuando se termine de leer este documento todas estas dudas se aclarar�n (aunque sea un poco). Todo lo que necesitar� es leer y practicar mucho.

Una cosa importante, es que sin_addr y sin_port, de la estructura sockaddr_in, deben ser del tipo Ordenaci�n de Bytes para Redes. Se ver�, en los ejemplos, las funciones que aqu� se describen para realizar estas conversiones, y a ese punto se entender�n mucho mejor.


Direcciones IP

En C, existen algunas funciones que nos ayudar�n a manipular direcciones IP. En esta secci�n se hablar� de las funciones inet_addr() y inet_ntoa().

Por un lado, la funci�n inet_addr() convierte una direcci�n IP en un entero largo sin signo (unsigned long int), por ejemplo:

		     
(...) 

dest.sin_addr.s_addr = inet_addr("195.65.36.12"); 

(...)

/*Recordar que esto ser�a as�, siempre que tengamos una estructura "dest" 
del tipo sockaddr_in*/

   

Por otro lado, inet_ntoa() convierte a una cadena que contiene una direcci�n IP en un entero largo. Por ejemplo:

		      
(...)

char *ip;

ip=inet_ntoa(dest.sin_addr);

printf("La direcci�n es: %s\n",ip);

(...)
    

Se deber� recordar tambi�n que la funci�n inet_addr() devuelve la direcci�n en formato de Ordenaci�n de Bytes para Redes por lo que no necesitaremos llamar a htonl().


Funciones Importantes

En esta secci�n, (en la cual se nombrar�n algunas de las funciones m�s utilizadas para la programaci�n en C de sockets), se mostrar� la sintaxis de la funci�n, las bibliotecas necesarias a incluir para llamarla, y algunos peque�os comentarios. Adem�s de las que se mencionan aqu�, existen muchas funciones m�s, aunque s�lo decid� incluir �stas. Tal vez sean incluidas en una futura versi�n de este documento[7]. Nuevamente, para ver ejemplos sobre el uso de estas funciones, se podr� leer la secci�n de nombre Un ejemplo de Servidor de Flujos y la secci�n de nombre Un ejemplo de Cliente de Flujos, en las cuales hay c�digo fuente de un Cliente de Flujos y un Servidor de Flujos.


socket()

     
#include <sys/types.h>
#include <sys/socket.h>

int socket(int domain,int type,int protocol);
     
	

Analicemos los argumentos:

  • domain. Se podr� establecer como AF_INET (para usar los protocolos ARPA de Internet), o como AF_UNIX (si se desea crear sockets para la comunicaci�n interna del sistema). �stas son las m�s usadas, pero no las �nicas. Existen muchas m�s, aunque no se nombrar�n aqu�.

  • type. Aqu� se debe especificar la clase de socket que queremos usar (de Flujos o de Datagramas). Las variables que deben aparecer son SOCK_STREAM o SOCK_DGRAM seg�n querramos usar sockets de Flujo o de Datagramas, respectivamente.

  • protocol. Aqu�, simplemente se puede establecer el protocolo a 0.

La funci�n socket() nos devuelve un descriptor de socket, el cual podremos usar luego para llamadas al sistema. Si nos devuelve -1, se ha producido un error (obs�rvese que esto puede resultar �til para rutinas de verificaci�n de errores).


bind()

     
#include <sys/types.h>
#include <sys/socket.h>

int bind(int fd, struct sockaddr *my_addr,int addrlen);
      
      

Analicemos los argumentos:

  • fd. Es el descriptor de fichero socket devuelto por la llamada a socket().

  • my_addr. es un puntero a una estructura sockaddr

  • addrlen. contiene la longitud de la estructura sockaddr a la cu�l apunta el puntero my_addr. Se deber�a establecer como sizeof(struct sockaddr).

La llamada bind() se usa cuando los puertos locales de nuestra m�quina est�n en nuestros planes (usualmente cuando utilizamos la llamada listen()). Su funci�n esencial es asociar un socket con un puerto (de nuestra m�quina). An�logamente socket(), devolver� -1 en caso de error.

Por otro lado podremos hacer que nuestra direcci�n IP y puerto sean elegidos autom�ticamente:

    
      server.sin_port = 0;                 /* bind() elegir� un puerto aleatoriamente */
      server.sin_addr.s_addr = INADDR_ANY; /* pone la Ip del seridor autom�ticamente  */
    
      

Un aspecto importante sobre los puertos y la llamada bind() es que todos los puertos menores que 1024 est�n reservados. Se podr� establecer un puerto, siempre que est� entre 1024 y 65535 (y siempre que no est�n siendo usados por otros programas).


connect()

      
#include <sys/types.h>
#include <sys/socket.h>

int connect(int fd, struct sockaddr *serv_addr, int addrlen);
 
      

Analicemos los argumentos:

  • fd. Deber�a configurarse como el fichero descriptor del socket, el cu�l fue devuelto por la llamada a socket().

  • serv_addr. Es un puntero a la estructura sockaddr la cu�l contiene la direcci�n IP destino y el puerto.

  • addrlen. An�logamente de lo que pasaba con bind(), este argumento deber�a establecerse como sizeof(struct sockaddr).

La funci�n connect() se usa para conectarse a un puerto definido en una direcci�n IP. Devolver� -1 si ocurre alg�n error.


listen()

      
#include <sys/types.h>
#include <sys/socket.h>

int listen(int fd,int backlog); 
 
      

Veamos los argumentos de listen():

  • fd. Es el fichero descriptor del socket, el cual fue devuelto por la llamada a socket()

  • backlog. Es el n�mero de conexiones permitidas.

La funci�n listen() se usa si se est�n esperando conexiones entrantes, lo cual significa, si se quiere, que alguien pueda conectarse a nuestra m�quina.

Despu�s de llamar a listen(), se deber� llamar a accept(), para as� aceptar las conexiones entrantes. La secuencia resumida de llamadas al sistema es:

  1. socket()

  2. bind()

  3. listen()

  4. accept()/* En la pr�xima secci�n se explicar� como usar esta llamada */

Como todas las funciones descritas arriba, listen() devolver� -1 en caso de error.


accept()

 
#include <sys/types.h>
#include <sys/socket.h>

int accept(int fd, void *addr, int *addrlen);
      

Veamos los argumentos de la funci�n:

  • fd. Es el fichero descriptor del socket, que fue devuelto por la llamada a listen().

  • addr. Es un puntero a una estructura sockaddr_in en la quel se pueda determinar qu� nodo nos est� contactando y desde qu� puerto.

  • addrlen. Es la longitud de la estructura a la que apunta el argumento addr, por lo que conviene establecerlo como sizeof(struct sockaddr_in), antes de que su direcci�n sea pasada a accept().

Cuando alguien intenta conectarse a nuestra computadora, se debe usar accept() para conseguir la conexi�n. Es muy f�cil de entender: alguien s�lo podr� conectarse (as�ciese con connect()) a nuestra m�quina, si nosotros aceptamos (as�ciese con accept()) ;-)

A continuaci�n, Se dar� un peque�o ejemplo del uso de accept() para obtener la conexi�n, ya que esta llamada es un poco diferente de las dem�s.

      
(...)

sin_size=sizeof(struct sockaddr_in);
/* En la siguiente l�nea se llama a accept() */ 
if ((fd2 = accept(fd,(struct sockaddr *)&client,&sin_size))==-1){ 
printf("accept() error\n");
exit(-1);
}

(...)

A este punto se usar� la variable fd2 para a�adir las llamadas send() y recv().


send()

      
#include <sys/types.h>
#include <sys/socket.h>

int send(int fd,const void *msg,int len,int flags);

Y sobre los argumentos de esta llamada:

  • fd. Es el fichero descriptor del socket, con el cual se desea enviar datos.

  • msg. Es un puntero apuntando al dato que se quiere enviar.

  • len. es la longitud del dato que se quiere enviar (en bytes).

  • flags. deber� ser establecido a 0[8] .

El prop�sito de esta funci�n es enviar datos usando sockets de flujo o sockets conectados de datagramas. Si se desea enviar datos usando sockets no conectados de datagramas debe usarse la llamada sendto(). Al igual que todas las dem�s llamadas que aqu� se vieron, send() devuelve -1 en caso de error, o el n�mero de bytes enviados en caso de �xito.


recv()

#include <sys/types.h>
#include <sys/socket.h>

int recv(int fd, void *buf, int len, unsigned int flags);

Veamos los argumentos:

  • fd. Es el descriptor del socket por el cual se leer�n datos.

    buf. Es el b�fer en el cual se guardar� la informaci�n a recibir.

    len. Es la longitud m�xima que podr� tener el b�ffer.

    flags. Por ahora, se deber� establecer como 0.

Al igual de lo que se dijo para send(), esta funci�n es usada con datos en sockets de flujo o sockets conectados de datagramas. Si se deseara enviar, o en este caso, recibir datos usando sockets desconectados de Datagramas, se debe usar la llamada recvfrom(). An�logamente a send(), recv() devuelve el n�mero de bytes le�dos en el b�fer, o -1 si se produjo un error.


recvfrom()

     
#include <sys/types.h>
#include <sys/socket.h>

int recvfrom(int fd,void *buf, int len, unsigned int flags
struct sockaddr *from, int *fromlen);
        
	

Veamos los argumentos:

  • fd. Lo mismo que para recv()

  • buf. Lo mismo que para recv()

  • len. Lo mismo que para recv()

  • flags. Lo mismo que para recv()

  • from. Es un puntero a la estructura sockaddr.

  • fromlen. Es un puntero a un entero local que deber�a ser inicializado a sizeof(struct sockaddr).

An�logamente a lo que pasaba con recv(), recvfrom() devuelve el n�mero de bytes recibidos, o -1 en caso de error.


close()

#include <unistd.h>

close(fd);

La funci�n close() es usada para cerrar la conexi�n de nuestro descriptor de socket. Si llamamos a close() no se podr� escribir o leer usando ese socket, y si alguien trata de hacerlo recibir� un mensaje de error.


shutdown()

  
#include <sys/socket.h>

int shutdown(int fd, int how);

Veamos los argumentos:

  • fd. Es el fichero descritor del socket al que queremos aplicar esta llamada.

  • how. S�lo se podr� establecer uno de estos nombres:

    • 0. Prohibido recibir.

    • 1. Prohibido enviar.

    • 2. Prohibido recibir y enviar.

Es lo mismo llamar a close() que establecer how a 2. shutdown() devolver� 0 si todo ocurre bien, o -1 en caso de error.


gethostname()

#include <unistd.h>

int gethostname(char *hostname, size_t size);

Veamos de qu� se tratan los argumentos:

  • hostname. Es un puntero a un array que contiene el nombre del nodo actual.

  • size. La longitud del array que contiene al nombre del nodo (en bytes).

La funci�n gethostname() es usada para obtener el nombre de la m�quina local.


Algunas palabras sobre dns

Esta secci�n fue creada ya que el lector deber�a saber qu� es un DNS.

DNS son las siglas de “Domain Name Service”[9] y, b�sicamente es usado para traducir direcciones IP. Por ejemplo, necesito saber la direcci�n IP del servidor queima.ptlink.net y usando el DNS puedo obtener la direcci�n IP 212.13.37.13.

Esto es importante en la medida de que las funciones que ya vimos (como bind() y connect()) son capaces de trabajar con direcciones IP.

Para mostrar c�mo se puede obtener la direcci�n IP de un servidor, por ejemplo de queima.ptlink.net, utilizando C, el autor ha realizado un peque�o ejemplo:

#include <stdio.h>
#include <netdb.h>   /* gethostbyname() necesita esta cabecera */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

  
int main(int argc, char *argv[])
{ 

   struct hostent *he;

   if (argc!=2) {
      printf("Uso: %s &lt;hostname&gt;\n",argv[0]);
      exit(-1);
   }

   if ((he=gethostbyname(argv[1]))==NULL) {
      printf("error de gethostbyname()\n");
      exit(-1);
   }

   printf("Nombre del host: %s\n",he->h_name);  
      /* muestra el nombre del nodo */
   printf("Direcci�n IP: %s\n",
          inet_ntoa(*((struct in_addr *)he->h_addr)));
      /* muestra la direcci�n IP */

}

	

Un ejemplo de Servidor de Flujos

En esta secci�n, se describir� un bonito ejemplo de un servidor de flujos. El c�digo fuente tiene muchos comentarios para que as�, al leerlo, no nos queden dudas.

Empecemos:

/* Estos son los ficheros de cabecera usuales */
#include <stdio.h>          
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>

#define PORT 3550 /* El puerto que ser� abierto */
#define BACKLOG 2 /* El n�mero de conexiones permitidas */

main()
{

   int fd, fd2; /* los ficheros descriptores */

   struct sockaddr_in server; 
   /* para la informaci�n de la direcci�n del servidor */

   struct sockaddr_in client; 
   /* para la informaci�n de la direcci�n del cliente */

   int sin_size;

   /* A continuaci�n la llamada a socket() */
   if ((fd=socket(AF_INET, SOCK_STREAM, 0)) == -1 ) {  
      printf("error en socket()\n");
      exit(-1);
   }

   server.sin_family = AF_INET;         

   server.sin_port = htons(PORT); 
   /* �Recuerdas a htons() de la secci�n "Conversiones"? =) */

   server.sin_addr.s_addr = INADDR_ANY; 
   /* INADDR_ANY coloca nuestra direcci�n IP autom�ticamente */

   bzero(&(server.sin_zero),8); 
   /* escribimos ceros en el reto de la estructura */


   /* A continuaci�n la llamada a bind() */
   if(bind(fd,(struct sockaddr*)&server,
           sizeof(struct sockaddr))==-1) {
      printf("error en bind() \n");
      exit(-1);
   }     

   if(listen(fd,BACKLOG) == -1) {  /* llamada a listen() */
      printf("error en listen()\n");
      exit(-1);
   }

   while(1) {
      sin_size=sizeof(struct sockaddr_in);
      /* A continuaci�n la llamada a accept() */
      if ((fd2 = accept(fd,(struct sockaddr *)&client,
                        &sin_size))==-1) {
         printf("error en accept()\n");
         exit(-1);
      }

      printf("Se obtuvo una conexi�n desde %s\n",
             inet_ntoa(client.sin_addr) ); 
      /* que mostrar� la IP del cliente */

      send(fd2,"Bienvenido a mi servidor.\n",22,0); 
      /* que enviar� el mensaje de bienvenida al cliente */

      close(fd2); /* cierra fd2 */
   }
}

Un ejemplo de Cliente de Flujos

Todo ser� an�logo a lo visto en la secci�n anterior.

    

#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>        
/* netbd.h es necesitada por la estructura hostent ;-) */

#define PORT 3550         
/* El Puerto Abierto del nodo remoto */

#define MAXDATASIZE 100   
/* El n�mero m�ximo de datos en bytes */

int main(int argc, char *argv[])
{
   int fd, numbytes;       
   /* ficheros descriptores */

   char buf[MAXDATASIZE];  
   /* en donde es almacenar� el texto recibido */

   struct hostent *he;         
   /* estructura que recibir� informaci�n sobre el nodo remoto */

   struct sockaddr_in server;  
   /* informaci�n sobre la direcci�n del servidor */

   if (argc !=2) { 
      /* esto es porque nuestro programa s�lo necesitar� un
      argumento, (la IP) */
      printf("Uso: %s <Direcci�n IP>\n",argv[0]);
      exit(-1);
   }

   if ((he=gethostbyname(argv[1]))==NULL){       
      /* llamada a gethostbyname() */
      printf("gethostbyname() error\n");
      exit(-1);
   }

   if ((fd=socket(AF_INET, SOCK_STREAM, 0))==-1){  
      /* llamada a socket() */
      printf("socket() error\n");
      exit(-1);
   }

   server.sin_family = AF_INET;
   server.sin_port = htons(PORT); 
   /* htons() es necesaria nuevamente ;-o */
   server.sin_addr = *((struct in_addr *)he->h_addr);  
   /*he->h_addr pasa la informaci�n de ``*he'' a "h_addr" */
   bzero(&(server.sin_zero),8);

   if(connect(fd, (struct sockaddr *)&server,
      sizeof(struct sockaddr))==-1){ 
      /* llamada a connect() */
      printf("connect() error\n");
      exit(-1);
   }

   if ((numbytes=recv(fd,buf,MAXDATASIZE,0)) == -1){  
      /* llamada a recv() */
      printf("Error en recv() \n");
      exit(-1);
   }

   buf[numbytes]='\0';

   printf("Mensaje del Servidor: %s\n",buf); 
   /* muestra el mensaje de bienvenida del servidor =) */

   close(fd);   /* cerramos fd =) */

}


�ltimas Palabras

En esta secci�n el autor de este documento, BracaMan, a�adir� algunas palabras. Se lo puede encontrar mandando un correo electr�nico a <BracaMan@clix.pt>. Su n�mero ICQ es 41476410 y se puede visitar por URL en http://www.BracaMan.net

Soy un simple humano, y como tal me equivoco, por lo que es casi seguro que haya errores en este documento. Y al decir errores me refiero a errores en el uso del Ingl�s[10] (no ser�a raro dado que �ste no es mi lenguaje nativo), como tambi�n errores t�cnicos. Ser�a muy bueno que si se encuentran errores en este tutorial, yo sea notificado v�a email.

Sin embargo, debe entenderse que �sta es simplemente la primera versi�n del documento, por lo que es natural que no est� muy completa (de hecho pienso que as� es), y tambi�n es natural que existan errores est�pidos. Sea como sea, puedo asegurar que los fragmentos de c�digo fuente que se encuentran en este documento funcionan perfectamente. Si se necesitara ayuda en lo que a esto respecta se puede contactarme mandando un email a <BracaMan@clix.pt>.

Agradecimientos especiales a: Ghost_Rider (mi viejo y querido camarada), Raven (por dejarme escribir este tutorial) y para todos mis amigos =)

Todos los copyrights est�n reservados. Se puede distribuir este tutorial libremente, siempre que no se cambie ning�n nombre ni URL. No se podr� cambiar una o dos l�neas del texto, o agregar algunas l�neas y luego decir que el autor de este tutorial eres t�. Si se desea cambiar algo en el documento, por favor av�same enviando un email a <BracaMan@clix.pt>.

En cuanto al traductor de este documento al espa�ol, su nombre es Sebasti�n Gurin, y se puede entrar en contacto con �l mand�ndole un correo a cancerbero_sgx@users.sourceforge.net. �l fue tambi�n quien ha dado formato usando DocBook -- SGML, versi�n 3.1 por lo que, si se encuentran errores tanto en el formato como en la traducci�n, se deber�an enviar comentarios a la direcci�n de correo electr�nico anterior.

Notas

[1]

Recu�rdese uno de los primeros conceptos que aprendemos al usar UNIX, “En un sistema Unix, todo es un fichero”. Nota del T.

[2]

Protocolo de Control de Transmisi�n. Nota del T.

[3]

Protocolo de los Datagramas de Usuario. Nota del T.

[4]

“nodo”'' ser� la traducci�n del t�rmino en ingl�s ``host'', que se usar� a lo largo de este texto. Nota del T.

[5]

que es la traducci�n al espa�ol de Network Byte Order. El t�rmino tambi�n es conocido como “Big-Endian Byte Order”. Tener en cuenta que, si no se habla de Ordenaci�n de Bytes para Redes, se hablar� de Ordenaci�n de Bytes para Nodos. Nota del T.

[6]

los cuales ocupan 2 y 4 bytes de memoria, respectivamente.

[7]

Se puede indagar m�s sobre �stas y las dem�s funciones relacionadas con Sockets en UNIX, leyendo las p�ginas de manual correspondientes a cada una. Nota del Traductor.

[8]

El argumento ``flags'', tambi�n contenido en otras funciones de manejo de sockets, no es una caracter�stica propia del mensaje, y puede omitirse. En este caso, hace distinci�n entre los modos de enviar un paquete, adem�s de otras cosas. Para m�s informaci�n, se puede leer el manual de send() (man 2 send). Nota del T.

[9]

que se traduce como “Servicio de Nombres de Dominio”. Nota del T

[10]

Seguramente tambi�n los haya en la traducci�n ;-). Nota del T.