Documentos de Académico
Documentos de Profesional
Documentos de Cultura
DPO3 U3 Contenido
DPO3 U3 Contenido
Desarrollo de software
Programa de la asignatura:
Programación orientada a objetos III
Unidad 3.
Programación en red
Clave:
15142423/ 16142524
Índice
Presentación de la unidad
Logros de la unidad
Competencia específica
Temario de la unidad
3. Programación en red
3.1. Modelo cliente-servidor
3.1.1. Cliente
3.1.2. Servidor
3.2. Streams
3.2.1. De entrada
3.2.2. De salida
3.3. Sockets
3.3.1. Apertura
3.3.2. Cierre
3. Programación en red
Hoy en día, la inmensa mayoría de las computadoras que existen intercambian información
unas con otras; para intercambiar información, ya sea personal, comercial, o sólo por
convivencia, las personas se encuentran en constante comunicación y, en dicha actividad,
las computadoras son de gran ayuda, para permitir una instantánea comunicación sin
importar las distancias. En el presente tema revisaremos lo que es la programación en red,
con lo que aprenderás a realizar programas que realicen un intercambio de información
entre computadoras.
Para lograr realizar esto, Java ha desarrollado clases que permiten la manipulación de los
puertos de las computadoras que permitan esta comunicación en red entre los diferentes
equipos.
Típicamente un cliente se reconoce como tal por ser quien comienza el intercambio de
información al realizar una petición al servidor, mientras que el servidor espera a que los
clientes le estén solicitando información para responderles.
Ahora bien, sólo resta apuntar que para poder realizar un programa que trabaje en red
deberás ajustarte al modelo cliente-servidor para el intercambio de información; por lo que,
como es de esperarse, se deberán crear dos programas, uno que funcionará en el cliente y
otro en el servidor. Más adelante, cuando veamos el tema de sockets, veremos un ejemplo
para crear un programa cliente y uno servidor, por el momento lo importante es que
comprendas este modelo de comunicación.
Para continuar con el tema, se revisará como al pretender mostrar u obtener alguna
información de un lugar externo, es necesario que el programa cree un flujo de datos para
poder manejarlos (algo parecido al canal de comunicación que se abre para conectarse a
una base de datos). Por lo tanto, hay un flujo de entrada que recibe los datos desde el
exterior del programa y un flujo de salida que envía los datos hacia el ordenador u otro
dispositivo de almacenamiento.
Los streams tal como menciona Abián (2004, p.18) “son tuberías o canales de
comunicaciones: tienen dos extremos entre los cuales fluyen los datos de manera continua”.
En esta misma obra puede verse en Abián (2004, p. 101) una clara descripción sobre lo que
son los streams y la distinción entre los flujos que toman datos desde una fuente externa
hacia el programa (stream de entrada) y por otra parte están los flujos que mueven datos
desde un programa hacía algún receptor externo (stream de salida).
Para el manejo flujos de entrada/salida, Java nos proporciona dos tipos de flujos posibles,
los de byte y los de caracteres. Los cuales se describen a continuación:
En Flujos de datos en Java de FIC (2007, p. 36), encontrarás la descripción de los procesos
para la lectura y escritura de datos mediante el manejo de streams.
Para conocer más a fondo las clases que controlan la entrada y salida de datos de un
programa revisa los siguientes textos1:
Para crear un puente entre dos equipos que pretenden conectarse se requiere de los
siguientes elementos: los sockets, que son básicamente cada uno de los extremos (en cada
equipo/computadora) que generan la comunicación entre dos programas que se estarán
comunicando en red. Por su parte los sockets requieren de conocerla dirección IP del equipo
con el que se entablará la comunicación, además del puerto al que se conectará, pues bien,
los puertos son las conexiones físicas que tiene un equipo para conectarse a la red.
1
Para profundizar en el tema y cumplir con las tareas de la unidad, ingresa a la sección de materiales de apoyo
de la unidad. Consulta los textos de la unidad que se agregan en formato PDF
De tal manera que un socket se comunica al equipo al que se quiere conectar mediante un
puerto.
El ciclo de vida de un canal de comunicación (socket), está determinado por tres fases, Díaz
(2011) las enlista de la siguiente manera:
• Creación y apertura del socket.
• Lectura y/o escritura, recepción y/o envío de datos por el socket.
• Destrucción, cierre del socket.
Ahora, revisa Programación con Sockets en FIC (2007, p. 13-15), donde encontrarás la
descripción del proceso de conexión entre un cliente y un servidor mediante sockets.
Revisando este material lograrás comprender el proceso de la conexión.
Para identificar las clases necesarias para la programación en red revisa Martínez (2000, p.
10), ahí encontrarás el nombre y descripción de las principales clases requeridas para la
creación de programas que funcionen en red y logren intercambiar información entre
diferentes equipos.
Para complementar la información revisa The Java Tutorials, la lección All About Sockets,
en Oracle (2012), donde encontrarás el tema de sockets completo, desde las explicaciones
teóricas respecto al tema, así como ejemplos básicos para la creación de programas en red,
resulta muy conveniente que revises el material completo, pues Oracle es dueño del
lenguaje Java, por lo que sus manuales contienen las referencias más precisas. Por lo tanto,
Ingresa a la liga:
http://docs.oracle.com/javase/tutorial/networking/sockets/index.html
/**
* Esta clase representa el programa servidor.
*/
public class Aplicacion_Servidor extends javax.swing.JFrame {
/**
* Creates new form Aplicacion_Servidor
*/
public Aplicacion_Servidor() {
initComponents();
}
SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
/* En esta sección se tienen los elementos que compondrán la apariencia gráfica
de la aplicación, declaraciones y acomodos en la pantalla */
txtPuertoSocket = new javax.swing.JTextField();
lblPuertoSocket = new javax.swing.JLabel();
btnAbrirPuerto = new javax.swing.JButton();
btnCerrarPuerto = new javax.swing.JButton();
jPanel1 = new javax.swing.JPanel();
jScrollPane1 = new javax.swing.JScrollPane();
txtaDatosEntrantes = new javax.swing.JTextArea();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Comunicacion con Sockets - Servidor");
txtPuertoSocket.setText("12345");
lblPuertoSocket.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblPuertoSocket.setText("Puerto:");
btnAbrirPuerto.setText("Abrir");
btnAbrirPuerto.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAbrirPuertoActionPerformed(evt);
}
});
btnCerrarPuerto.setText("Cerrar");
btnCerrarPuerto.setEnabled(false);
btnCerrarPuerto.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnCerrarPuertoActionPerformed(evt);
}
});
jPanel1.setBorder(javax.swing.BorderFactory.createTitledBorder("Datos
Recibidos"));
jPanel1.setEnabled(false);
jPanel1.setLayout(new java.awt.BorderLayout());
txtaDatosEntrantes.setColumns(20);
txtaDatosEntrantes.setEditable(false);
txtaDatosEntrantes.setRows(5);
txtaDatosEntrantes.setEnabled(false);
jScrollPane1.setViewportView(txtaDatosEntrantes);
jPanel1.add(jScrollPane1, java.awt.BorderLayout.CENTER);
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addComponent(lblPuertoSocket,
javax.swing.GroupLayout.PREFERRED_SIZE, 74,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(txtPuertoSocket,
javax.swing.GroupLayout.PREFERRED_SIZE, 111,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnAbrirPuerto)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCerrarPuerto)
.addGap(0, 40, Short.MAX_VALUE))
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
.addContainerGap())
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new
java.awt.Component[] {btnAbrirPuerto, btnCerrarPuerto});
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPuertoSocket,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPuertoSocket)
.addComponent(btnAbrirPuerto)
.addComponent(btnCerrarPuerto))
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, 162,
Short.MAX_VALUE)
.addContainerGap())
);
java.awt.Dimension screenSize =
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-403)/2, (screenSize.height-253)/2, 403, 253);
}// </editor-fold>
/* Aquí se termina la creación de la apariencia gráfica */
/**
* El método principal invoca a que se ejecute la aplicación del servidor */
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
{
String msg = null;
int puerto = 0;
try
{
//Establecemos el puerto a través del cual se abrirá el socket.
puerto = Integer.valueOf(txtPuertoSocket.getText().trim());
//Se asigna ese Puerto al socket creado
serverSocket = new ServerSocket(puerto);
conexiones.
serverSocket.close();
cliente = null;
serverSocket = null;
habilitarControlesAperturaDeSocket(true);
}
}
/* En el caso de que no se pueda cerrar el socket se captura la excepción y
se cierra el sistema */
catch (Exception e)
{
msg = "Error al intentar cerrar el socket.\n\n" +
"El sistema se cerrara después de este cuadro de dialogo.";
JOptionPane.showMessageDialog(this, msg, "Error",
JOptionPane.ERROR_MESSAGE);
e.printStackTrace();
}
}
/* El siguiente método es para leer los datos que el cliente envía hacia el
servidor */
public void leerDatosDelCliente()
{
Thread t = null;
catch (Exception e)
{
e.printStackTrace();
}
}
}
};
t = new Thread(r);
/**
* Esta clase representa el programa cliente.
*/
public class Aplicacion_Cliente extends javax.swing.JFrame {
/**
* Creates new form Aplicacion_Servidor
*/
public Aplicacion_Cliente() {
initComponents();
}
SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">
private void initComponents() {
/* En esta sección se tienen los elementos que compondrán la apariencia grafica
de la aplicación, declaraciones y acomodos en la pantalla */
txtPuertoSocket = new javax.swing.JTextField();
lblPuertoSocket = new javax.swing.JLabel();
btnAbrirPuerto = new javax.swing.JButton();
btnCerrarPuerto = new javax.swing.JButton();
lblIp = new javax.swing.JLabel();
txtIp = new javax.swing.JTextField();
txtDatos = new javax.swing.JTextField();
btnEnviarDatos = new javax.swing.JButton();
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
setTitle("Comunicacion con Sockets - Cliente");
txtPuertoSocket.setText("12345");
lblPuertoSocket.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblPuertoSocket.setText("Puerto:");
btnAbrirPuerto.setText("Abrir");
btnAbrirPuerto.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnAbrirPuertoActionPerformed(evt);
}
});
btnCerrarPuerto.setText("Cerrar");
btnCerrarPuerto.setEnabled(false);
lblIp.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);
lblIp.setText("Ip:");
txtIp.setText("127.0.0.1");
txtDatos.addKeyListener(new java.awt.event.KeyAdapter() {
public void keyReleased(java.awt.event.KeyEvent evt) {
txtDatosKeyReleased(evt);
}
});
btnEnviarDatos.setText("Enviar");
btnEnviarDatos.addActionListener(new java.awt.event.ActionListener() {
public void actionPerformed(java.awt.event.ActionEvent evt) {
btnEnviarDatosActionPerformed(evt);
}
});
javax.swing.GroupLayout(getContentPane());
getContentPane().setLayout(layout);
layout.setHorizontalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap()
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING, false)
.addComponent(lblPuertoSocket,
javax.swing.GroupLayout.DEFAULT_SIZE,
74, Short.MAX_VALUE)
.addComponent(lblIp,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE))
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.LEADING,
false)
.addGroup(layout.createSequentialGroup()
.addComponent(txtPuertoSocket,
javax.swing.GroupLayout.PREFERRED_SIZE,
111,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(
javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnAbrirPuerto)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnCerrarPuerto))
.addComponent(txtIp)))
.addGroup(layout.createSequentialGroup()
.addComponent(txtDatos,
javax.swing.GroupLayout.PREFERRED_SIZE, 258,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addComponent(btnEnviarDatos)))
.addContainerGap(49, Short.MAX_VALUE))
);
layout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new
layout.setVerticalGroup(
layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
.addGroup(layout.createSequentialGroup()
.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE,
Short.MAX_VALUE)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(lblIp)
.addComponent(txtIp, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtPuertoSocket,
javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(lblPuertoSocket)
.addComponent(btnAbrirPuerto)
.addComponent(btnCerrarPuerto))
.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
.addGroup(layout.createParallelGroup(
javax.swing.GroupLayout.Alignment.BASELINE)
.addComponent(txtDatos, javax.swing.GroupLayout.PREFERRED_SIZE,
javax.swing.GroupLayout.DEFAULT_SIZE,
javax.swing.GroupLayout.PREFERRED_SIZE)
.addComponent(btnEnviarDatos))
.addGap(179, 179, 179))
);
java.awt.Dimension screenSize =
java.awt.Toolkit.getDefaultToolkit().getScreenSize();
setBounds((screenSize.width-402)/2, (screenSize.height-145)/2, 402, 145);
}// </editor-fold>
/* Aquí se termina la creación de la apariencia gráfica */
/* Se tiene un manejo de evento sobre txtDatos para estar escuchando cada una de las
teclas que se oprimen */
private void txtDatosKeyReleased(java.awt.event.KeyEvent evt) {
// TODO add your handling code here:
if (evt.getKeyCode() == evt.VK_ENTER)
enviarDatos();
}
/**
* El método principal invoca a que se ejecute la aplicación del cliente */
*/
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
Override
public void run() {
new Aplicacion_Cliente().setVisible(true);
}
});
}
/*A continuación se presenta el método que envía datos, el cual primero los obtiene
de txtDatos y después los envía mediante un DataOutputStream */
public void enviarDatos()
{
try
{
escritor.writeUTF(txtDatos.getText());
}
catch (Exception e)
{
e.printStackTrace();
}
Ya que concluiste con el análisis de las clases que controlan servidor y las clases que
controlan clientes, realiza tu Autoevaluación.
Cierre de la unidad
Has concluido la tercera unidad de la asignatura. A lo largo de esta unidad revisaste los
principios del modelo de comunicaciones Cliente – Servidor, de esta misma manera
abordaste el tema de Streams, que como sabes se requieren para el intercambio de
información y, en esta unidad, pudiste utilizarlos para que ese intercambio de información se
realice entre diferentes computadoras. Por último, revisaste la manipulación de sockets para
realizar una conexión entre diferentes equipos que permita el intercambio de datos mediante
estos.
Al concluir esta unidad, concluyes también la materia Programación Orientada a Objetos III,
en ella te adentraste en conceptos avanzados de la programación, iniciaste en la unidad
uno con el manejo de archivos que te permitan almacenar información o extraerla, en la
unidad dos abordaste la programación paralela mediante threads y, por último, en esta
unidad generaste programas en red que intercambien información entre diferentes
computadoras. Con la aplicación de estos temas ampliarás la gama de desarrollos de
software en los que podrás participar.
Es aconsejable que revises nuevamente la unidad en caso de que los temas que se acaban
de mencionar no te sean familiares o no los recuerdes, de no ser este tu caso, ¡Felicidades!
concluiste con la asignatura Programación Orientada a Objetos III.
Para que puedas ejecutar los programas que se te presentan, así como las actividades es
importante que instales un IDE en tu computadora, se recomienda NetBeans, puedes
descargarlo de forma gratuita de la siguiente liga: http://netbeans.org/downloads/
Es recomendable que pruebes los códigos que se presentan en los ejemplos que se
encuentran en cada fuente de consulta mencionada.
Fuentes de consulta
Bibliografía Básica