Anda di halaman 1dari 13

PROGRAMACIN CLIENTE-SERVIDOR

MEDIANTE SOCKETS EN JAVA

Qu es la arquitectura cliente servidor?


La arquitectura cliente-servidor es un modelo de aplicacin distribuida en el que las tareas
se reparten entre los proveedores de recursos o servicios, llamados servidores, y los
demandantes, llamados clientes. Es decir, un cliente es el que hace una solicitud de un
servicio a un servidor y el servidor es un programa que recibe una solicitud, realiza el
servicio requerido y devuelve los resultados en forma de una respuesta.

Qu es un socket?
Los sockets son un sistema de comunicacin entre procesos de diferentes mquinas de
una red. Ms exactamente, un socket es un punto de comunicacin por el cual un
proceso puede emitir o recibir informacin.

Cmo funciona un socket?


El modelo bsico de los sockets consta de 2 simples programas, un servidor y un cliente.
Bsicamente el programa SERVIDOR comienza a escuchar en un puerto determinado
(nosotros lo especificamos), y posteriormente el programa CLIENTE debe conocer la IP o
nombre de dominio/hostname del servidor y el puerto que est escuchando.
El socket sigue normalmente realiza los procesos de Abrir-Leer-Escribir-Cerrar. Antes de que
un proceso de usuario pueda realizar operaciones de entrada/salida, debe hacer una
llamada a Abrir (open), luego realizar llamadas a Leer (read) y Escribir (write), para la
lectura y escritura de los datos y una vez concluido el intercambio de informacin, el
proceso de usuario llamar a Cerrar (close) para informar que ha finalizado.
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 llamados sockets.
El ciclo de vida de un descriptor, aplicado a un canal de comunicacin (por ejemplo, un
socket), est determinado por tres fases:

Creacin, apertura del socket


Lectura y Escritura, recepcin y envo de datos por el socket
Destruccin, cierre del socket

En un esquema ms completo donde se tiene muchos clientes con peticiones a un solo


servidor se puede apreciar cmo se realiza la comunicacin con el siguiente esquema
que se muestra.

Ejemplo 1
SALUDO DE BIENVENIDA
El siguiente programa establece una conexin bsica entre un servidor y un cliente
Donde una vez establecida la conexin el servidor solicita el nombre del cliente, el cliente
introduce su nombre, y el servidor le da una bienvenida mediante un mensaje.
Programa Servidor
//Declaramos libreras necesarias
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Servidor {
private ServerSocket sServidor; //Socket del servidor
private Socket sCliente; //Socket para el cliente
private Scanner entrada; //Flujo de Entrada para envio de datos
private PrintStream salida; //Flujo de Salida para recepcion de datos
private int puerto; // Puerto por el cual escuchara el servidor
public Servidor(int p){
puerto=p;
}
public void iniciar(){
try {
//Se Crea el socket del servidor
sServidor =new ServerSocket(puerto);
System.out.println(" - SERVIDOR INICIADO - ");
System.out.println(" - Esprando Cliente - ");
//El metodo accept(), espera hasta que un cliente realice una conexin
//Una vez que se ha establecido una conexin por el cliente, este
//mtodo devolver un objeto tipo Socket, a travs del cual se establecer
//la comunicacin con el cliente
sCliente=sServidor.accept();
//Obtengo una referencia a los flujos de datos de entrada y salida del socket cliente
entrada =new Scanner(sCliente.getInputStream());
salida =new PrintStream(sCliente.getOutputStream());
////Esta seccin puede ser modificada segn nuestros requerimientos//////////
System.out.println("Cliente Conectado:"+ sCliente.getInetAddress() +":"+
sCliente.getPort() );
salida.println("EJEMPLO1-Saludo");
salida.print("Ingrese Su Nombre ->");
String nombre= entrada.next();
salida.println("Bienvenido "+ nombre);
/////////////////////////////////////////////////////////////////////////////
//Cerramos la conexin
finalizar();
}
catch(Exception e){
finalizar ();
e.printStackTrace();
}
}
public void finalizar(){
try {
entrada.close();
salida.close();
sCliente.close();
sServidor.close();
System.out.print("Conexion Finalizada...");
}

catch (IOException e) {
e.printStackTrace();
}
}}

public class Main {


public static void main(String arg[]){
Servidor x=new Servidor(9998);
x.iniciar();
}
}

Capturas

Iniciando el servidor

Estableciendo conexin desde el cliente mediante telnet

Resultado, una vez introducido nuestro nombre el servidor nos manda un mensaje de
bienvenida

Ejemplo 2
Chat simple
El siguiente programa establece una conexin bsica entre un servidor y un cliente
Donde una vez establecida la conexin el servidor y el cliente, pueden chatear entre ellos,
hasta que los dos introduzcan la palabra bye.
Programa Servidor
//Importamos libreras necesarias
import java.io.*;
import java.net.*;
import java.util.Scanner;
import java.awt.event.*;
public class Servidor {
private ServerSocket sServidor; //Socket del servidor
private Socket sCliente; //Socket para el cliente
private Scanner entrada; //Flujo de Entrada para envio de datos
private PrintStream salida; //Flujo de Salida para recepcion de datos
private int puerto; // Puerto por el cual escuchara el servidor
private String mensaje_enviar="";
private String mensaje_recibido="";
private javax.swing.Timer t; //Declaramos un Timer
public Servidor (int p){
puerto=p;
//El timer ser el encargado de ejecutar este bloque de cdigo cada 500 [ms]
//Es decir, que este leer y mostrara los mensajes recibidos cada 0.5 segundos
//siempre o cuando se haya creado una conexin y exista un mensaje.
t = new javax.swing.Timer(500,new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (sCliente.isConnected() && !mensaje_recibido.equals("bye")){
mensaje_recibido=entrada.next();
System.out.println("Cliente_dice:"+mensaje_recibido);
}
}
});
}
public void iniciar(){
try{
//Inicamos el servidor
sServidor =new ServerSocket(puerto);
System.out.println(" - SERVIDOR INICIADO- ");
System.out.println("- Esperando cliente ...");
//El metodo accept(), espera hasta que un cliente realice una conexin
//Una vez que se ha establecido una conexin por el cliente, este
//mtodo devolver un objeto tipo Socket, a travs del cual se establecer
//la comunicacin con el cliente.
sCliente=sServidor.accept();
//Obtengo una referencia a los flujos de datos de entrada y salida del socket cliente
salida=new PrintStream(sCliente.getOutputStream());
entrada =new Scanner(sCliente.getInputStream());
System.out.println("Cliente conectado "+ sCliente.getInetAddress()+":"+
sCliente.getPort()+"\n");
//iniciamos el timer
t.start();
Scanner lector=new Scanner(System.in);
//Escribimos los mensajes hacia el cliente

while(!mensaje_recibido.equals("bye"))
{
mensaje_enviar=lector.next();
salida.println("Servidor Dice : " +mensaje_enviar);
}
//Terminamos la conexin
finalizar();
}
catch(Exception e){
e.printStackTrace();
finalizar();
}
}
public void finalizar(){
try{
t.stop();
salida.close();
entrada.close();
sCliente.close();
sServidor.close();
}
catch(Exception e){
e.printStackTrace();
}
}
}

public class Main {


public static void main(String arg[]){
Servidor x=new Servidor(9999);
x.iniciar();
}
}

Capturas

Iniciando el servidor

Conectando el cliente al servidor

Resultado, una vez establecida la conexin podemos proceder a chatear entre un


servidor y un cliente.

Ejemplo 3
Eco
El siguiente programa establece una conexin bsica entre un servidor y un cliente
Donde una vez establecida la conexin el servidor solicita que introduzca un texto al
cliente y el servidor devuelve un eco, es decir el mismo mensaje que se envi. A
continuacin se implementa el programa del servidor conjuntamente el programa del
cliente.
Programa Servidor
import java.io.*;
import java.net.*;
import java.util.*;
public class Servidor {
private ServerSocket sServidor;
private Socket sCliente;
private Scanner entrada;
private PrintStream salida;
private int puerto;
private String mensaje="";

public Servidor (int p){


puerto =p;
}
public void iniciar(){
try{
sServidor=new ServerSocket(puerto);
System.out.println(" - SERVIDOR INICIADO - ");
System.out.println(" - Esperando Cliente - ");
sCliente=sServidor.accept();
entrada=new Scanner(sCliente.getInputStream());
salida = new PrintStream(sCliente.getOutputStream());
//Se reenva los mensajes que van llegando hasta q el cliente introduzca la palabra
//bye,
while(!mensaje.equals("bye")){
mensaje=entrada.next();
System.out.println("Mensaje cliente: "+mensaje);
salida.println("Eco:_"+mensaje);
}
finalizar();
}
catch(Exception e){
e.printStackTrace();
finalizar();
}
}
public void finalizar(){
try{
salida.close();
entrada.close();
sCliente.close();
sServidor.close();
System.out.print("Conexion Finalizada!!");
}catch(Exception e)
{
e.printStackTrace();
}
}
}

public class MainServidor {


public static void main(String arg[]){
Servidor x=new Servidor(9990);
x.iniciar();
}
}

Programa Cliente
import
import
import
public

java.io.*;
java.net.*;
java.util.Scanner;
class Cliente {
private Socket sCliente;
private Scanner entrada;
prvate PrintStream salida;
prvate String host; //IP del servidor con el que me voy a conectar
private int puerto;
private String mensaje="";
public Cliente(String h, int p){
host=h;
puerto=p;
}
public void iniciar(){
try{

//Estableciendo conexion con el servidor


sCliente =new Socket(host,puerto);
System.out.println("CONEXION INICIADA");
System.out.println("Conectado a : "+ sCliente.getRemoteSocketAddress());
//Obtengo una referencia a los flujos de datos de entrada y salida
salida=new PrintStream(sCliente.getOutputStream());
entrada=new Scanner(sCliente.getInputStream());

//Este bloque de cdigo se encarga de enviar mensajes al servidor hasta que


//este introduzca la palabra bye
Scanner lectura=new Scanner(System.in);
while (!mensaje.equals("bye")){
System.out.print("\nDigite mensaje :");
mensaje=lectura.next();
salida.println(mensaje);
System.out.print(entrada.next());
}
finalizar();
}
catch(Exception e){
e.printStackTrace();
finalizar();
}
}
public void finalizar(){
try{
salida.close();
entrada.close();
sCliente.close();}
catch(Exception e){
e.printStackTrace();
}
}
}

public class MainCliente {


public static void main(String arg[]){
Cliente c=new Cliente("127.0.0.1", 9990);
c.iniciar();
}
}

Capturas

Iniciando el servidor

Estableciendo conexin desde el cliente, iniciando cliente

Resultados, enviando mensajes y retornado ecos


Por parte del cliente

Por parte del servidor

Ejemplo 4
Enviar un correo mediante un socket cliente.
El siguiente programa cliente establece enva un correo mediante SMTP.
En este ejemplo se enviara un correo electrnico a un servidor SMTP (implementado en el
laboratorio anterior). Cabe notar que solo es necesario codificar el programa cliente,
debido a que el protocolo SMTP ya esta implementado y configurado con Postfix.
Programa Cliente
//Importando libreras necesarias
import java.io.*;
import java.net.*;
import java.util.Scanner;
public class Cliente {
private Socket sCliente;
private Scanner entrada;
private PrintStream salida;
private String host="";
private int puerto;

public Cliente(String h, int p){


host=h;
puerto=p;
}
public void iniciar(String correoOrigen, String correoDestino, String asunto,String mensaje){
try{
//Estableciendo conexion con el servidor SMTP
sCliente =new Socket(host,puerto);
System.out.println("CONEXION INICIADA");
System.out.println("Conectado a : "+ sCliente.getRemoteSocketAddress());
//Obtengo una referencia a los flujos de datos de entrada y salida
salida=new PrintStream(sCliente.getOutputStream());
entrada=new Scanner(sCliente.getInputStream());
//Escribiendo el correo (Notese que se sigue el formato propio del SMTP )
System.out.println(entrada.nextLine()); //Respuesta del servidor
salida.println("MAIL FROM: "+correoOrigen); //Correo de Origen
System.out.println(entrada.nextLine()); //Respuesta del servidor
salida.println("RCPT TO: "+correoDestino); //Correo de Destino
System.out.println(entrada.nextLine()); //Respuesta del servidor
salida.println("DATA"); //Indicamos q mandaremos un Mensaje
salida.println("Subject: "+asunto); //Asunto del correo
System.out.println(entrada.nextLine()); //Respuesta del servidor
salida.println(mensaje); //Mensaje
salida.println(".");
salida.println("."); //Terminamos el mensaje
salida.println("quit");
System.out.println(entrada.nextLine()); //Respuesta del servidor
System.out.println("\nCorreo Enviado!");
finalizar();
}
catch(Exception e){
e.printStackTrace();
finalizar();
}
}
public void finalizar(){
try{
salida.close();
entrada.close();
sCliente.close();}
catch(Exception e){

e.printStackTrace();
}
}
}

public class MainCliente {


public static void main(String [] args) {
Cliente c=new Cliente("127.0.0.1", 25); //Servidor SMTP
c.iniciar("jaime@info.net", //Correo Origen
"telematica@info.net", //Correo Destino
"Prueba De envi Socket", //Asunto
"Hola servidor esta es una prueba de Correo mediante Sockets"); //Mensaje
}
}

Capturas
Asumiendo que el servidor est bien configurado y se encuentra en marcha, procedemos a
mandar el correo.

Ingresando al cliente de correo (Thunderbird que configuramos el anterior laboratorio)

Revisamos si el correo llego en forma adecuada.

NOTA
* Ambos programas (servidor y cliente) no necesitan estar programados en Java, es
posible programarlos en lenguajes de programacin diferentes, o inclusive programar un
servidor en java y utilizar un cliente ya existente o solo programar el cliente y acceder a un
servidor ya existente.
* Cuando se selecciona un nmero de puerto, se debe tener en cuenta que los puertos en
el rango 0-1023 estn reservados. Estos puertos son los que utilizan los servicios estndar del
sistema como email, ftp, http, dns, dhcp, etc. Por lo que, para aplicaciones de usuario, el
programador deber asegurarse de seleccionar un puerto por encima del 1023.
* El cliente debe de conocer tanto el puerto a utilizar como la IP o dominio del servidor,
mientras el servidor solo debe conocer el puerto de conexin.
* Si las pruebas son realizadas en Windows 7, es necesario habilitar el telnet en Panel de
control -> Desinstalar un programa -> Activar o desactivar las caractersticas de Windows > cliente telnet.

Anda mungkin juga menyukai