En aquest tema, aprendrem sobre ServerSocket, una classe fonamental en Java per a la creació de servidors que poden acceptar connexions de clients a través de la xarxa. Aquesta classe és part del paquet java.net i proporciona les eines necessàries per a la comunicació de xarxa a nivell de servidor.

Objectius

  • Entendre què és un ServerSocket i com funciona.
  • Aprendre a crear un servidor bàsic que accepti connexions de clients.
  • Gestionar múltiples connexions de clients.
  • Implementar un servidor multithreaded per a una millor gestió de les connexions.

Què és un ServerSocket?

Un ServerSocket és una classe que espera connexions entrants en un port específic. Quan un client intenta connectar-se a aquest port, el ServerSocket accepta la connexió i crea un Socket per a la comunicació amb el client.

Creació d'un ServerSocket

Exemple Bàsic

A continuació, es mostra un exemple bàsic de com crear un ServerSocket que escolta en el port 1234 i accepta una connexió de client:

import java.io.*;
import java.net.*;

public class SimpleServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(1234)) {
            System.out.println("Server is listening on port 1234");
            Socket socket = serverSocket.accept();
            System.out.println("New client connected");

            InputStream input = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));

            String message = reader.readLine();
            System.out.println("Received: " + message);

            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Explicació del Codi

  1. Creació del ServerSocket:

    ServerSocket serverSocket = new ServerSocket(1234);
    

    Això crea un ServerSocket que escolta en el port 1234.

  2. Acceptació de Connexions:

    Socket socket = serverSocket.accept();
    

    El mètode accept() espera fins que un client es connecti al servidor. Quan això passa, retorna un objecte Socket que representa la connexió amb el client.

  3. Lectura de Dades:

    InputStream input = socket.getInputStream();
    BufferedReader reader = new BufferedReader(new InputStreamReader(input));
    String message = reader.readLine();
    

    Aquestes línies llegeixen un missatge enviat pel client.

  4. Tancament del Socket:

    socket.close();
    

    Finalment, es tanca la connexió amb el client.

Gestió de Múltiples Connexions

Per gestionar múltiples connexions de clients, podem utilitzar fils (threads). Cada vegada que un client es connecta, creem un nou fil per gestionar la comunicació amb aquest client.

Exemple de ServerSocket Multithreaded

import java.io.*;
import java.net.*;

public class MultiThreadedServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(1234)) {
            System.out.println("Server is listening on port 1234");

            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println("New client connected");

                new ClientHandler(socket).start();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

class ClientHandler extends Thread {
    private Socket socket;

    public ClientHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            InputStream input = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));

            String message;
            while ((message = reader.readLine()) != null) {
                System.out.println("Received: " + message);
            }

            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Explicació del Codi

  1. Bucle Infinit:

    while (true) {
        Socket socket = serverSocket.accept();
        new ClientHandler(socket).start();
    }
    

    El servidor entra en un bucle infinit esperant connexions de clients. Cada vegada que un client es connecta, es crea un nou fil ClientHandler per gestionar la connexió.

  2. Classe ClientHandler:

    class ClientHandler extends Thread {
        private Socket socket;
    
        public ClientHandler(Socket socket) {
            this.socket = socket;
        }
    
        public void run() {
            // Gestió de la comunicació amb el client
        }
    }
    

    La classe ClientHandler extén Thread i gestiona la comunicació amb el client dins del mètode run().

Exercicis Pràctics

Exercici 1: Servidor Echo

Crea un servidor que llegeixi missatges dels clients i els retorni (echo) al client.

Solució

import java.io.*;
import java.net.*;

public class EchoServer {
    public static void main(String[] args) {
        try (ServerSocket serverSocket = new ServerSocket(1234)) {
            System.out.println("Server is listening on port 1234");

            while (true) {
                Socket socket = serverSocket.accept();
                new EchoClientHandler(socket).start();
            }
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

class EchoClientHandler extends Thread {
    private Socket socket;

    public EchoClientHandler(Socket socket) {
        this.socket = socket;
    }

    public void run() {
        try {
            InputStream input = socket.getInputStream();
            BufferedReader reader = new BufferedReader(new InputStreamReader(input));

            OutputStream output = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(output, true);

            String message;
            while ((message = reader.readLine()) != null) {
                System.out.println("Received: " + message);
                writer.println("Echo: " + message);
            }

            socket.close();
        } catch (IOException ex) {
            ex.printStackTrace();
        }
    }
}

Exercici 2: Servidor de Fitxers

Crea un servidor que permeti als clients pujar i baixar fitxers.

Solució

Aquest exercici és més complex i requereix una comprensió avançada de la gestió de fitxers i la comunicació de xarxa. Es recomana dividir-lo en passos més petits i implementar-lo progressivament.

Conclusió

En aquest tema, hem après a utilitzar la classe ServerSocket per crear servidors en Java. Hem vist com acceptar connexions de clients i gestionar múltiples connexions utilitzant fils. A més, hem practicat amb exercicis per reforçar els conceptes apresos. Amb aquests coneixements, estàs preparat per crear aplicacions de servidor més complexes i robustes.

Curs de Programació en Java

Mòdul 1: Introducció a Java

Mòdul 2: Flux de Control

Mòdul 3: Programació Orientada a Objectes

Mòdul 4: Programació Orientada a Objectes Avançada

Mòdul 5: Estructures de Dades i Col·leccions

Mòdul 6: Gestió d'Excepcions

Mòdul 7: Entrada/Sortida de Fitxers

Mòdul 8: Multithreading i Concurrència

Mòdul 9: Xarxes

Mòdul 10: Temes Avançats

Mòdul 11: Frameworks i Llibreries de Java

Mòdul 12: Construcció d'Aplicacions del Món Real

© Copyright 2024. Tots els drets reservats