[código] Conexiones Cliente-Servidor mediante sockets en Java
Por falta de tiempo me es imposible explicar este código detalladamente, tal como me gustarÃa, pero no tengo otra opción que simplemente ponerlo. Aún asà es de recordar que pueden dejar todos los comentarios que deseen, con sus dudas y sugerencias (que no pedidos de tareas).
Aún asà explico un poco el resultado del programa... el programa es un chat simple (muy simple), que usa Sockets para crear conexiones de red. Consta de un servidor (Servidor.java) y un cliente (Cliente.java), mediante los cuales se puede establecer una conversación. Si se escribe "TERMINAR" (sin comillas), la conexión se cierra.
El resultado


El código
El código fuente de Servidor.java:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Servidor extends JFrame {
private JTextField campoIntroducir;
private JTextArea areaPantalla;
private ObjectOutputStream salida;
private ObjectInputStream entrada;
private ServerSocket servidor;
private Socket conexion;
private int contador = 1;
// configurar GUI
public Servidor()
{
super( "Servidor" );
Container contenedor = getContentPane();
// crear campoIntroducir y registrar componente de escucha
campoIntroducir = new JTextField();
campoIntroducir.setEditable( false );
campoIntroducir.addActionListener(
new ActionListener() {
// enviar mensaje al cliente
public void actionPerformed( ActionEvent evento )
{
enviarDatos( evento.getActionCommand() );
campoIntroducir.setText( "" );
}
}
);
contenedor.add( campoIntroducir, BorderLayout.NORTH );
// crear areaPantalla
areaPantalla = new JTextArea();
contenedor.add( new JScrollPane( areaPantalla ),
BorderLayout.CENTER );
setSize( 300, 150 );
setVisible( true );
} // fin del constructor de Servidor
// configurar y ejecutar el servidor
public void ejecutarServidor()
{
// configurar servidor para que reciba conexiones; procesar las conexiones
try {
// Paso 1: crear un objeto ServerSocket.
servidor = new ServerSocket( 12345, 100 );
while ( true ) {
try {
esperarConexion(); // Paso 2: esperar una conexión.
obtenerFlujos(); // Paso 3: obtener flujos de entrada y salida.
procesarConexion(); // Paso 4: procesar la conexión.
}
// procesar excepción EOFException cuando el cliente cierre la conexión
catch ( EOFException excepcionEOF ) {
System.err.println( "El servidor terminó la conexión" );
}
finally {
cerrarConexion(); // Paso 5: cerrar la conexión.
++contador;
}
} // fin de instrucción while
} // fin del bloque try
// procesar problemas con E/S
catch ( IOException excepcionES ) {
excepcionES.printStackTrace();
}
} // fin del método ejecutarServidor
// esperar que la conexión llegue, después mostrar información de la conexión
private void esperarConexion() throws IOException
{
mostrarMensaje( "Esperando una conexión\n" );
conexion = servidor.accept(); // permitir al servidor aceptar la conexión
mostrarMensaje( "Conexión " + contador + " recibida de: " +
conexion.getInetAddress().getHostName() );
}
// obtener flujos para enviar y recibir datos
private void obtenerFlujos() throws IOException
{
// establecer flujo de salida para los objetos
salida = new ObjectOutputStream( conexion.getOutputStream() );
salida.flush(); // vaciar búfer de salida para enviar información de encabezado
// establecer flujo de entrada para los objetos
entrada = new ObjectInputStream( conexion.getInputStream() );
mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );
}
// procesar la conexión con el cliente
private void procesarConexion() throws IOException
{
// enviar mensaje de conexión exitosa al cliente
String mensaje = "Conexión exitosa";
enviarDatos( mensaje );
// habilitar campoIntroducir para que el usuario del servidor pueda enviar mensajes
establecerCampoTextoEditable( true );
do { // procesar los mensajes enviados por el cliente
// leer el mensaje y mostrarlo en pantalla
try {
mensaje = ( String ) entrada.readObject();
mostrarMensaje( "\n" + mensaje );
}
// atrapar problemas que pueden ocurrir al tratar de leer del cliente
catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {
mostrarMensaje( "\nSe recibió un tipo de objeto desconocido" );
}
} while ( !mensaje.equals( "CLIENTE>>> TERMINAR" ) );
} // fin del método procesarConexion
// cerrar flujos y socket
private void cerrarConexion()
{
mostrarMensaje( "\nFinalizando la conexión\n" );
establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir
try {
salida.close();
entrada.close();
conexion.close();
}
catch( IOException excepcionES ) {
excepcionES.printStackTrace();
}
}
// enviar mensaje al cliente
private void enviarDatos( String mensaje )
{
// enviar objeto al cliente
try {
salida.writeObject( "SERVIDOR>>> " + mensaje );
salida.flush();
mostrarMensaje( "\nSERVIDOR>>> " + mensaje );
}
// procesar problemas que pueden ocurrir al enviar el objeto
catch ( IOException excepcionES ) {
areaPantalla.append( "\nError al escribir objeto" );
}
}
// método utilitario que es llamado desde otros subprocesos para manipular a
// areaPantalla en el subproceso despachador de eventos
private void mostrarMensaje( final String mensajeAMostrar )
{
// mostrar mensaje del subproceso de ejecución despachador de eventos
SwingUtilities.invokeLater(
new Runnable() { // clase interna para asegurar que la GUI se actualice apropiadamente
public void run() // actualiza areaPantalla
{
areaPantalla.append( mensajeAMostrar );
areaPantalla.setCaretPosition(
areaPantalla.getText().length() );
}
} // fin de la clase interna
); // fin de la llamada a SwingUtilities.invokeLater
}
// método utilitario que es llamado desde otros subprocesos para manipular a
// campoIntroducir en el subproceso despachador de eventos
private void establecerCampoTextoEditable( final boolean editable )
{
// mostrar mensaje del subproceso de ejecución despachador de eventos
SwingUtilities.invokeLater(
new Runnable() { // clase interna para asegurar que la GUI se actualice apropiadamente
public void run() // establece la capacidad de modificar a campoIntroducir
{
campoIntroducir.setEditable( editable );
}
} // fin de la clase interna
); // fin de la llamada a SwingUtilities.invokeLater
}
public static void main( String args[] )
{
JFrame.setDefaultLookAndFeelDecorated(true);
Servidor aplicacion = new Servidor();
aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
aplicacion.ejecutarServidor();
}
} // fin de la clase Servidor
El código fuente de Cliente.java:
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
public class Cliente extends JFrame {
private JTextField campoIntroducir;
private JTextArea areaPantalla;
private ObjectOutputStream salida;
private ObjectInputStream entrada;
private String mensaje = "";
private String servidorChat;
private Socket cliente;
// inicializar servidorChat y configurar GUI
public Cliente( String host )
{
super( "Cliente" );
servidorChat = host; // establecer el servidor al que se va a conectar este cliente
Container contenedor = getContentPane();
// crear campoIntroducir y registrar componente de escucha
campoIntroducir = new JTextField();
campoIntroducir.setEditable( false );
campoIntroducir.addActionListener(
new ActionListener() {
// enviar mensaje al servidor
public void actionPerformed( ActionEvent evento )
{
enviarDatos( evento.getActionCommand() );
campoIntroducir.setText( "" );
}
}
);
contenedor.add( campoIntroducir, BorderLayout.NORTH );
// crear areaPantalla
areaPantalla = new JTextArea();
contenedor.add( new JScrollPane( areaPantalla ),
BorderLayout.CENTER );
setSize( 300, 150 );
setVisible( true );
} // fin del constructor de Cliente
// conectarse al servidor y procesar mensajes del servidor
private void ejecutarCliente()
{
// conectarse al servidor, obtener flujos, procesar la conexión
try {
conectarAServidor(); // Paso 1: crear un socket para realizar la conexión
obtenerFlujos(); // Paso 2: obtener los flujos de entrada y salida
procesarConexion(); // Paso 3: procesar la conexión
}
// el servidor cerró la conexión
catch ( EOFException excepcionEOF ) {
System.err.println( "El cliente termino la conexión" );
}
// procesar los problemas que pueden ocurrir al comunicarse con el servidor
catch ( IOException excepcionES ) {
excepcionES.printStackTrace();
}
finally {
cerrarConexion(); // Paso 4: cerrar la conexión
}
} // fin del método ejecutarCliente
// conectarse al servidor
private void conectarAServidor() throws IOException
{
mostrarMensaje( "Intentando realizar conexión\n" );
// crear Socket para realizar la conexión con el servidor
cliente = new Socket( InetAddress.getByName( servidorChat ), 12345 );
// mostrar la información de la conexión
mostrarMensaje( "Conectado a: " +
cliente.getInetAddress().getHostName() );
}
// obtener flujos para enviar y recibir datos
private void obtenerFlujos() throws IOException
{
// establecer flujo de salida para los objetos
salida = new ObjectOutputStream( cliente.getOutputStream() );
salida.flush(); // vacÃar búfer de salida para enviar información de encabezado
// establecer flujo de entrada para los objetos
entrada = new ObjectInputStream( cliente.getInputStream() );
mostrarMensaje( "\nSe recibieron los flujos de E/S\n" );
}
// procesar la conexión con el servidor
private void procesarConexion() throws IOException
{
// habilitar campoIntroducir para que el usuario del cliente pueda enviar mensajes
establecerCampoTextoEditable( true );
do { // procesar mensajes enviados del servidor
// leer mensaje y mostrarlo en pantalla
try {
mensaje = ( String ) entrada.readObject();
mostrarMensaje( "\n" + mensaje );
}
// atrapar los problemas que pueden ocurrir al leer del servidor
catch ( ClassNotFoundException excepcionClaseNoEncontrada ) {
mostrarMensaje( "\nSe recibió un objeto de tipo desconocido" );
}
} while ( !mensaje.equals( "SERVIDOR>>> TERMINAR" ) );
} // fin del método procesarConexion
// cerrar flujos y socket
private void cerrarConexion()
{
mostrarMensaje( "\nCerrando conexión" );
establecerCampoTextoEditable( false ); // deshabilitar campoIntroducir
try {
salida.close();
entrada.close();
cliente.close();
}
catch( IOException excepcionES ) {
excepcionES.printStackTrace();
}
}
// enviar mensaje al servidor
private void enviarDatos( String mensaje )
{
// enviar objeto al servidor
try {
salida.writeObject( "CLIENTE>>> " + mensaje );
salida.flush();
mostrarMensaje( "\nCLIENTE>>> " + mensaje );
}
// procesar los problemas que pueden ocurrir al enviar el objeto
catch ( IOException excepcionES ) {
areaPantalla.append( "\nError al escribir el objeto" );
}
}
// método utilitario que es llamado desde otros subprocesos para manipular a
// areaPantalla en el subproceso despachador de eventos
private void mostrarMensaje( final String mensajeAMostrar )
{
// mostrar mensaje del subproceso de ejecución de la GUI
SwingUtilities.invokeLater(
new Runnable() { // clase interna para asegurar que la GUI se actualice apropiadamente
public void run() // actualiza areaPantalla
{
areaPantalla.append( mensajeAMostrar );
areaPantalla.setCaretPosition(
areaPantalla.getText().length() );
}
} // fin de la clase interna
); // fin de la llamada a SwingUtilities.invokeLater
}
// método utilitario que es llamado desde otros subprocesos para manipular a
// campoIntroducir en el subproceso despachador de eventos
private void establecerCampoTextoEditable( final boolean editable )
{
// mostrar mensaje del subproceso de ejecución de la GUI
SwingUtilities.invokeLater(
new Runnable() { // clase interna para asegurar que la GUI se actualice apropiadamente
public void run() // establece la capacidad de modificar campoIntroducir
{
campoIntroducir.setEditable( editable );
}
} // fin de la clase interna
); // fin de la llamada a SwingUtilities.invokeLater
}
public static void main( String args[] )
{
JFrame.setDefaultLookAndFeelDecorated(true);
Cliente aplicacion;
if ( args.length == 0 )
aplicacion = new Cliente( "127.0.0.1" );
else
aplicacion = new Cliente( args[ 0 ] );
aplicacion.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
aplicacion.ejecutarCliente();
}
} // fin de la clase Cliente









josue dice:
Noviembre 20th, 2008 a las 2:23 pm
hola yo necesito crear un cliente y un servidor, bueno en realidad lo que necesito hacer es un messenger y comunicarme con otros servidores y clientes pero no tengo idea de como empezar si alguien me puede ayudar se lo agradecerÃa mucho……
Cristian dice:
Noviembre 20th, 2008 a las 7:35 pm
Entonces échale un ojo a este ejercicio, puedes basarte en el y copiar lo que quieras:
http://casidiablo.net/casidiablo-chat/
Un saludo!
Pedro dice:
Diciembre 11th, 2008 a las 1:15 am
Hola !!
primero que nada felicidades por tu web esta muy linda e interesante ,bueno tengo una duda sobre un trabajo que me dieron se trata de esto:
1.-Tengo que conectarme de una maquina con linux a una en con windows usando rdesktop
2.-Configurar una clase Cliente(mejor si es en java) para ejecutar rdeskpot en el servidor y mandarle la IP de la compu que me quiero conectar
A mi parecer ese es mi trabajo por que mi docente la verdad que no es muy especifico solo nos dijo que queria “Escritorio Remoto” en modo grafico usando linux y rdesktop y cualquier lenguaje para el Cliente
Bueno si contestas muchas gracias…
bye
pedro dice:
Diciembre 11th, 2008 a las 1:20 am
Hola yo de nuevo…
no pretendo que me lo hagas la tarea sino que talves me puedas orientar un poco para hacer ese trabajoon del que te comente antes
Cristian dice:
Diciembre 11th, 2008 a las 10:27 am
Pues si es con rdesktop, pues lo tienes demasiado fácil, digo yo. ¿has usado rdesktop alguna vez? ¿que Linux estás usando?
Por lo demás, busca información en Google de cómo ejecutar comandos del sistema con Java, hay bastante sobre ello.
Un saludo!
pedro dice:
Diciembre 11th, 2008 a las 11:44 pm
Hola cristian gracias por la respuesta
Hoy hable con el docente y eso tambien yo creia que era muy facil porque el a dio 20 pts del trabajo al codigo y la verdad para este trabajo no se va ausar nada de codigo!!
el dijo que la cosa es que funcione la verdad no le entiendo nos dio hasta el sabado y mi idea es esta desde una ventana echa en java llamar a la aplicacion rdeskpot y que haga su trabajo , lo que si quiere es que todo corra bajo linux y conectarse a otra computadora tb con linux con java se puede no? es igual que en windows?
como llamo desde un programa en java a una aplicacion linux?? Hay que configurar las maquinas que tienen linux para conexion remota?? .Se que son muchas preguntas y talves no tengas tiempo de responderme algunas pero no importa por lo demas yo pongo de mi parte es que la verdad cuando uno empioeza siempre cuesta no?
bueno bye y muchas gracias por responder
Ahora yo te respondo alo que me preguntaste tengo linux XUBUNTU y windows XP, el linux no lo uso mucho por que se vuelve un poco lento especialmente cuando abro firefox pero lo tengo.
Y rdespot lo baje pero nunca lo use tengo un problema al instalarlo primero me pedia gcc y luego la libreria X-Window como los consigo?
Cristian dice:
Diciembre 12th, 2008 a las 10:19 am
OK. NO he usado Xubuntu, pero, por si acaso, ejecuta antes que nada esto:
sudo aptitude install rdesktop.Por lo demás, como te decÃa, hay bastante información de cómo ejecutar comandos con Java. Hay tanta, que me da vergüenza ponerte algo, pero, bueno, te doy una pista:
Process p = Runtime.getRuntime().exec("rdesktop nombre_computador");Un saludo!
pedro dice:
Diciembre 12th, 2008 a las 10:42 pm
Gracias!!
cristian me sirvio de mucho tu ayuda!!
gracias por tu tiempo