Documentos de Académico
Documentos de Profesional
Documentos de Cultura
ORIZABA
MATERIA
Programación en ambiente cliente/servidor
PRESENTA
DOCENTE
Altamirano Cruz Luis Enrique
CARRERA
INGENERIA INFORMATICA
10° SEMESTRE
2.1. Concepto de socket.
Un socket (enchufe), es un método para la comunicación entre un programa
del cliente y un programa del servidor en una red, se define, por tanto, como el
punto final en una conexión.
Para ello son necesarios los tres recursos que originan el concepto de socket:
Es muy común en este tipo de comunicación lanzar un proceso hijo, una vez
realizada la conexión, que se ocupe del intercambio de información con el
proceso cliente mientras el proceso padre servidor sigue aceptando
conexiones. Para eliminar esta característica se cerrará el descriptor del socket
servidor con nombre en cuanto realice una conexión con un proceso socket
cliente.
El proceso de lectura toma los datos desde el objeto y los transfiere al proceso
de usuario, mientras que el de escritura los transfiere desde el proceso de
usuario al objeto. Una vez concluido el intercambio de información, el
proceso de usuario llamará a Cerrar (close) para informar al sistema operativo
que ha finalizado la utilización del fichero o dispositivo.
En Unix, un proceso tiene un conjunto de descriptores de entrada/salida desde
donde leer y por donde escribir. Estos descriptores pueden estar referidos a
ficheros, dispositivos, o canales de comunicaciones sockets.
Pero el desarrollo del proyecto relativo al lenguaje oak siguió adelante gracias
entre otras cosas a la distribución libre del lenguaje por Internet mediante la
incipiente, por aquellos años, World Wide Web. De esta forma el lenguaje
alcanzó cierto auge y un gran número de programadores se encargaron de su
depuración así como de perfilar la forma y usos del mismo.
El nombre de Java, surgió durante una de las sesiones de brain storming que
se celebraban por el equipo de desarrollo del lenguaje. Hubo que cambiar el
nombre debido a que ya existía otro lenguaje con el nombre de oak.
Cabe reseñar que un cauce de comunicación normal tiene las cuatro primeras
propiedades, pero no las dos últimas.
Los dos tipos de sockets más utilizados son los dos primeros.
El dominio de un socket.
Indica el formato de las direcciones que podrán tomar los sockets y los
protocolos que soportarán dichos sockets.
La estructura genérica es
struct sockaddr {
u__short sa__family; /* familia */
char sa__data[14]; /* dirección */
};
Pueden ser:
struct in__addr {
u__long s__addr;
};
struct sockaddr__in {
short sin_family; /* en este caso AF_INET */
u__short sin_port; /* numero del puerto */
struct in__addr sin__addr; /* direcc Internet */
char sin_zero[8]; /* campo de 8 ceros */
};
Estos dominios van a ser los utilizados en xshine. Pero existen otros
como:
* Dominio AF_NS:
Servidor y cliente deben estar en una red XEROX.
* Dominio AF_CCITT:
Para protocolos CCITT, protocolos X25, ...
struct sockaddr {
};
Pero en el caso de que estemos tratando con una aplicación particular, esta
estructura se deberá reemplazar por la estructura correspondiente del dominio
de comunicaciones utilizado, ya que por desgracia, no todas las familias de
direcciones se ajustan a la estructura genérica descrita.
También podemos ver el dominio UNIX (AF_UNIX), donde los sockets son
locales al sistema en el cual han sido definidos. Permiten la comunicación
interna de procesos, y su designación se realiza por medio de una referencia
UNIX.
struct sockaddr_un {
};
AF_DECnet /* DECnet */
PrintStream salida;
try {
salida = new PrintStream( miCliente.getOutputStream() );
} catch( IOException e ) {
System.out.println( e );
}
La clase PrintStream tiene métodos para la representación textual de todos los
datosprimitivos de Java. Sus métodos write y println() tienen una especial
importancia en este aspecto.No obstante, para el envío de información al
servidor también podemos utilizarDataOutputStream:
DataOutputStream salida;
try {
salida = new DataOutputStream( miCliente.getOutputStream() );
} catch( IOException e ) {
System.out.println( e );
}
La clase DataOutputStream permite escribir cualquiera de los tipos primitivos
de Java, muchos de sus métodos escriben un tipo de dato primitivo en el
stream de salida. De todos esos métodos, el más útil quizás sea writeBytes().
En el lado del SERVIDOR, podemos utilizar la clase PrintStream para enviar
información al cliente:
PrintStream salida;
try {
salida = new PrintStream( socketServicio.getOutputStream() );
Cierre de Sockets
Siempre deberemos cerrar los canales de entrada y salida que se hayan abierto
durante la ejecución de la aplicación.
En la parte del cliente:
try {
salida.close();
entrada.close();
miCliente.close();
} catch( IOException e ) {
System.out.println( e );
}
Y en la parte del servidor:
try {
salida.close();
entrada.close();
socketServicio.close();
miServicio.close();
} catch( IOException e ) {
System.out.println( e );
}
ServerSocket
Es un objeto utilizado en las aplicaciones servidor para escuchar las peticiones
que realicen los clientes conectados a ese servidor. Este objeto no realiza el
servicio, sino que crea un objeto Socket en función del cliente para realizar
toda la comunicación a través de él.
DatagramSocket
La clase de sockets datagrama puede ser utilizada para implementar
datagramas no fiables (sockets UDP), no ordenados. Aunque la comunicación
por estos sockets es muy rápida porque no hay que perder tiempo
estableciendo la conexión entre cliente y servidor.
DatagramPacket
Clase que representa un paquete datagrama conteniendo información de
paquete, longitud de paquete, direcciones Internet y números de puerto.
MulticastSocket
Clase utilizada para crear una versión multicast de la clase socket datagrama.
Múltiples clientes/servidores pueden transmitir a un grupo multicast (un grupo
de direcciones IP compartiendo el mismo número de puerto).
NetworkServer
Una clase creada para implementar métodos y variables utilizadas en la
creación de un servidorTCP/IP.
NetworkClient
Una clase creada para implementar métodos y variables utilizadas en la
creación de un clienteTCP/IP.
SocketImpl
Es un Interface que nos permite crearnos nuestro propio modelo de
comunicación. Tendremos que implementar sus métodos cuando la usemos. Si
vamos a desarrollar una aplicación con requerimientos especiales de
comunicaciones, como pueden ser la implementación de un corta fuegos (TCP
es un protocolo no seguro), o acceder a equipos especiales (como un lector de
código de barras o un GPS diferencial), necesitaremos nuestra propia clase
Socket.
import java.io. *;
import java.net. *;
tratar {
echoSocket = new Socket ("taranis", 7);
out = new PrintWriter (echoSocket.getOutputStream (), true);
in = new BufferedReader (new InputStreamReader (
echoSocket.getInputStream ()));
} catch (UnknownHostException e) {
System.err.println ("No sé sobre host: taranis.");
System.exit (1);
} captura (IOException e) {
System.err.println ("No se pudo obtener E / S para"
+ "la conexión a: taranis.");
System.exit (1);
}
fuera.close ();
cercar();
stdIn.close ();
echoSocket.close ();
}
}
Tenga en cuenta que EchoClient escribe y lee desde su socket, enviando
datos al servidor Echo y recibiendo datos del mismo.
Veamos el programa e investiguemos las partes interesantes. Las tres
afirmaciones en el tratar bloque de la principal El método es crítico. Estas
líneas establecen la conexión de socket entre el cliente y el servidor y abren
una PrintWriter y un BufferedReader en el zócalo:
echoSocket = new Socket ("taranis", 7);
out = new PrintWriter (echoSocket.getOutputStream (), true);
in = new BufferedReader (new InputStreamReader
(echoSocket.getInputStream ()));
La primera declaración en esta secuencia crea una nueva Enchufe objeto y
lo nombra echoSocket . los Enchufe El constructor utilizado aquí requiere
el nombre de la máquina y el número de puerto al que desea conectarse. El
programa de ejemplo usa el nombre de host taranis. Este es el nombre de una
máquina hipotética en nuestra red local. Cuando escribe y ejecuta este
programa en su máquina, cambie el nombre del host al nombre de una
máquina en su red. Asegúrese de que el nombre que utiliza sea el nombre IP
completo de la máquina a la que desea conectarse. El segundo argumento es el
número de puerto. El número de puerto 7 es el puerto en el que escucha el
servidor Echo.
La segunda declaración obtiene el flujo de salida del socket y abre
un PrintWriter en eso. De manera similar, la tercera instrucción obtiene el
flujo de entrada del socket y abre un BufferedReader en eso. El ejemplo
utiliza lectores y escritores para que pueda escribir caracteres Unicode en el
socket.
Para enviar datos a través del socket al servidor, EchoClient simplemente
tiene que escribir al PrintWriter . Para obtener la respuesta del
servidor, EchoClient lee desde el BufferedReader . El resto del programa lo
consigue. Si aún no está familiarizado con las clases de E / S de la plataforma
Java, puede leer I / O básico .
La siguiente parte interesante del programa es la mientras lazo. El bucle lee
una línea a la vez desde el flujo de entrada estándar y lo envía inmediatamente
al servidor escribiéndolo en el PrintWriter conectado al zócalo:
String userInput;
while ((userInput = stdIn.readLine ())! = null) {
out.println (userInput);
System.out.println ("echo:" + in.readLine ());
}
La última afirmación en el mientras bucle lee una línea de información de
la BufferedReader conectado al zócalo. los readLine El método espera
hasta que el servidor devuelve la información a EchoClient .
Cuando readline devoluciones, EchoClient Imprime la información a la
salida estándar.
los mientras el bucle continúa hasta que el usuario escribe un carácter de
final de entrada. Es decir, EchoClient lee la entrada del usuario, la envía al
servidor Echo, obtiene una respuesta del servidor y la muestra hasta que llega
al final de la entrada. los mientras entonces el bucle termina y el programa
continúa, ejecutando las siguientes cuatro líneas de código:
fuera.close ();
cercar();
stdIn.close ();
echoSocket.close ();
Estas líneas de código entran en la categoría de limpieza. Un programa de
buen comportamiento siempre se limpia después de sí mismo, y este programa
tiene un buen comportamiento. Estas declaraciones cierran los lectores y
escritores conectados al socket y al flujo de entrada estándar, y cierran la
conexión del socket al servidor. El orden aquí es importante. Debe cerrar todas
las secuencias conectadas a un socket antes de cerrar el socket.
Este programa cliente es sencillo y simple porque el servidor Echo
implementa un protocolo simple. El cliente envía texto al servidor, y el
servidor lo repite. Cuando sus programas cliente están hablando con un
servidor más complicado como un servidor HTTP, su programa cliente
también será más complicado. Sin embargo, los conceptos básicos son muy
similares a los de este programa:
1. Abra un zócalo.
2. Abra un flujo de entrada y un flujo de salida al socket.
3. Lea y escriba en el flujo de acuerdo con el protocolo del servidor.
4. Cierra los arroyos.
5. Cierre el zócalo.
Solo el paso 3 difiere de cliente a cliente, dependiendo del servidor. Los otros
pasos siguen siendo en gran medida los mismos.