¿Qué es un servidor?

Servidor

Cualquier programa que espera por una petición entrante de comunicación
proveniente de un cliente y que extrae la información de la petición de los
datos recibidos y devuelve el resultado al cliente

Algoritmo básico

while (true) {
    Esperar por una petición entrante;
    Realizar las acciones necesarias para satisfacer la petición;
}


Algunas Cuestiones Básicas acerca de los Servidores


Sockets

Streams frente a Buffers

Los lenguajes de programación proporcionan acceso a los datos de un socket a través de:

El acceso a los streams es más fácil, mientras que el acceso a los buffers puede ser más rápido

Se tratará primero el acceso mediante streams.


Sockets TCP Java

Clases Principales

ServerSocket

Utilizados por los servidores para escuchar a los clientes

Socket

Utilizados por los clientes para hablar con los servidores
Utilizados por los servidores para hablar con los clientes

Métodos básicos de la clase ServerSocket

public ServerSocket(int port) //port = 0 significa que se asigna un puerto aleatoriamente
public ServerSocket(int port, int backlog)
public ServerSocket(int port, int backlog, InetAddress bindAddress)

public Socket accept() throws IOException
public void close() throws IOException
public int getLocalPort()

Métodos básicos de la clase Socket

public InputStream getInputStream() throws IOException
public OutputStream getOutputStream() throws IOException


Un Servidor Sencillo de Fechas

import java.net.Socket;
import java.net.ServerSocket;
import java.io.*;
import java.util.Date;

class ServidorFechasSencillo {

    public static void main(String[] args) throws IOException {
        ServerSocket ser_sersock = new ServerSocket(0);
        System.out.println("Servidor inicializado, escuchando en el puerto " +
                            ser_sersock.getLocalPort());
        while (true) {
            Socket ser_clisock = ser_sersock.accept();
            procesarPeticion(ser_clisock.getInputStream(),
                             ser_clisock.getOutputStream());
            ser_clisock.close();
        }
    }


Procesamiento de las Peticiones del Cliente

    static void procesarPeticion(InputStream in,OutputStream out) throws IOException {
        BufferedReader parsedInput = new BufferedReader(new InputStreamReader(in));
        // el argumento "true" es para conseguir el "auto-volcado" del flujo de salida
        PrintWriter parsedOutput = new PrintWriter(out,true);
        String inputLine = parsedInput.readLine();
        if (inputLine.startsWith("date")) {
            Date fecha = new Date();
            parsedOutput.println(fecha.toString());
        }
    }
}

Nota: Este servidor es un primer ejemplo y necesita muchas mejoras, que habrá que hacer en esta práctica.


Ejecución del Servidor 

Nota: la entrada por teclado aparece en negrilla

localhost->java SimpleDateServer &
[1] 16269
Servidor inicializado, escuchando en el puerto 62047

localhost->telnet localhost 62047
Trying 128.0.0.1...
Connected to localhost.
Escape character is '^]'.
date hoy
Sun Mar 19 17:37:30 PDT 2006
Connection closed by foreign host.

localhost->telnet localhost 62047
Trying 128.0.0.1...
Connected to localhost.
Escape character is '^]'.
time
Connection closed by foreign host.


Advertencias acerca del uso del telnet

El uso de telnet para interactuar con el servidor es:

No conviene diseñar un servidor, asumiendo que interactuará directamente con el usuario final


Cuestiones acerca del Servidor Sencillo

El procesamiento de una petición bloquea cualquier otra conexión

    Utilizando la primera versión del ServidorFechaSencillo

Solución:

    Múltiples conexiones necesitan ser aceptadas concurrentemente.


Enunciado Práctica 1

Modificar el código del ServidorFechasSencillo para conseguir que sea un servidor concurrente, utilizando hilos de ejecución.