i Socket in Java

In Java, un socket è un endpoint per la comunicazione tra due macchine. Consenti lo scambio bidirezionale di dati tra i dispositivi connessi.

Immagina che tu abbia un client e un server che vogliono comunicare tra loro. Il client apre una socket e si connette al server, che ha anche una socket in ascolto. Una volta stabilita la connessione, il client e il server possono inviare e ricevere dati attraverso le loro socket.

La comunicazione avviene attraverso il passaggio di pacchetti di dati, che viaggiano da una socket all’altra. Ogni pacchetto di dati contiene informazioni come l’indirizzo IP del mittente e del destinatario, oltre ai dati effettivi.

Questo è un esempio semplificato di come funzionano i socket in Java. In pratica, ci sono molte altre informazioni e dettagli che vengono gestiti automaticamente dalla libreria di socket di Java.

Connessione con i socket in Java

Ecco un esempio di come un socket possa essere utilizzato per consentire al client di connettersi al server:

LATO SERVER:

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

public class Server {
   public static void main(String[] args) throws IOException {
      ServerSocket serverSocket = new ServerSocket(8080);
      Socket clientSocket = serverSocket.accept();
      PrintWriter out =
          new PrintWriter(clientSocket.getOutputStream(), true);
      BufferedReader in = new BufferedReader(
          new InputStreamReader(clientSocket.getInputStream()));
      String inputLine;
      while ((inputLine = in.readLine()) != null) {
         out.println(inputLine);
      }
   }
}

LATO CLIENT:

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

public class Client {
   public static void main(String[] args) throws IOException {
      Socket socket = new Socket("localhost", 8080);
      PrintWriter out =
          new PrintWriter(socket.getOutputStream(), true);
      BufferedReader in =
          new BufferedReader(
              new InputStreamReader(socket.getInputStream()));
      BufferedReader stdIn =
          new BufferedReader(
              new InputStreamReader(System.in));
      String userInput;
      while ((userInput = stdIn.readLine()) != null) {
         out.println(userInput);
         System.out.println("echo: " + in.readLine());
      }
   }
}

Chat room con i socket

Il codice si divide in due parti: il server e il client.

Il codice del server ha la seguente logica:

  1. Il server crea un oggetto ServerSocket su una porta specifica (ad esempio, la porta 8080).
  2. Il server attende connessioni dai client accettando le richieste di connessione con il metodo accept() sull’oggetto ServerSocket.
  3. Ogni volta che un client si connette, il server crea un nuovo oggetto Socket per gestire la comunicazione con quel client e lo aggiunge alla lista di client connessi.
  4. Per ogni client connesso, il server avvia un thread separato che gestisce la ricezione dei messaggi dal client.
  5. Il thread legge i messaggi dal socket del client con l’oggetto BufferedReader e li inoltra a tutti i client connessi tramite il loro socket.

Il codice del client ha la seguente logica:

  1. Il client crea un oggetto Socket che si connette al server sulla porta specifica (8080).
  2. Il client avvia due thread separati, uno per inviare messaggi al server e l’altro per ricevere messaggi dal server.
  3. Il thread di invio legge i messaggi da tastiera e li invia al server tramite l’oggetto PrintWriter.
  4. Il thread di ricezione legge i messaggi dal socket del server con l’oggetto BufferedReader e li stampa sullo schermo.

Questo è il funzionamento generale dell’esempio di chat room con socket in Java. In pratica, ci sono molte altre funzionalità che potrebbero essere aggiunte, come la gestione degli errori o la possibilità di disconnettersi dalla chat room, ma questo esempio di base dovrebbe darti un’idea di come funzionano i socket in Java.

Lato Server:

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

public class ChatServer {
   private static List<Socket> socketList = new ArrayList<>();

   public static void main(String[] args) throws IOException {
      ServerSocket serverSocket = new ServerSocket(9090);
      System.out.println("Server started");

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

         new Thread(() -> {
            try {
               BufferedReader reader = new BufferedReader(
                   new InputStreamReader(socket.getInputStream()));
               while (true) {
                  String message = reader.readLine();
                  if (message == null) {
                     break;
                  }
                  System.out.println("Received message: " + message);
                  broadcastMessage(message, socket);
               }
            } catch (IOException e) {
               e.printStackTrace();
            }
         }).start();
      }
   }

   private static void broadcastMessage(String message, Socket sender)
       throws IOException {
      for (Socket socket : socketList) {
         if (!socket.equals(sender)) {
            PrintWriter writer = new PrintWriter(socket.getOutputStream());
            writer.println(message);
            writer.flush();
         }
      }
   }
}

Lato client:

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

public class ChatClient {
   public static void main(String[] args) throws IOException {
      Socket socket = new Socket("localhost", 9090);

      Scanner scanner = new Scanner(System.in);
      PrintWriter writer = new PrintWriter(socket.getOutputStream());
      BufferedReader reader = new BufferedReader(
          new InputStreamReader(socket.getInputStream()));

      System.out.println("Connected to server");

      new Thread(() -> {
         try {
            while (true) {
               String message = reader.readLine();
               if (message == null) {
                  break;
               }
               System.out.println("Received message: " + message);
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
      }).start();

      while (true) {
         String message = scanner.nextLine();
         writer.println(message);
         writer.flush();
      }
   }
}

File Sharing

Il codice si divide in due parti: il server e il client.

Il codice del server ha la seguente logica:

  1. Il server crea un oggetto ServerSocket su una porta specifica (ad esempio, la porta 8080).
  2. Il server attende connessioni dai client accettando le richieste di connessione con il metodo accept() sull’oggetto ServerSocket.
  3. Ogni volta che un client si connette, il server crea un nuovo oggetto Socket per gestire la comunicazione con quel client.
  4. Il server legge la richiesta del client sul socket con l’oggetto BufferedReader e determina il nome del file richiesto.
  5. Il server apre il file richiesto e lo invia al client tramite il socket con l’oggetto FileInputStream e BufferedOutputStream.

Il codice del client ha la seguente logica:

  1. Il client crea un oggetto Socket che si connette al server sulla porta specifica (8080).
  2. Il client invia una richiesta al server per un file specifico tramite il socket con l’oggetto PrintWriter.
  3. Il client riceve il file dal server tramite il socket con l’oggetto BufferedInputStream e lo salva sul disco locale con l’oggetto FileOutputStream.

Questo è il funzionamento generale dell’esempio di file sharing con socket in Java. In pratica, ci sono molte altre funzionalità che potrebbero essere aggiunte, come la gestione degli errori o la verifica dell’integrità del file ricevuto, ma questo esempio di base dovrebbe darti un’idea di come funzionano i socket in Java per lo scambio di file.

Lato server:

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

public class FileServer {
   public static void main(String[] args) throws IOException {
      ServerSocket serverSocket = new ServerSocket(8080);

      System.out.println("Server started");

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

         BufferedReader reader = new BufferedReader(
             new InputStreamReader(socket.getInputStream()));
         String fileName = reader.readLine();

         File file = new File(fileName);
         if (!file.exists()) {
            PrintWriter writer = new PrintWriter(socket.getOutputStream());
            writer.println("File not found");
            writer.flush();
            socket.close();
            continue;
         }

         byte[] fileBytes = new byte[(int) file.length()];
         FileInputStream fileInputStream = new FileInputStream(file);
         fileInputStream.read(fileBytes);
         fileInputStream.close();

         OutputStream outputStream = socket.getOutputStream();
         outputStream.write(fileBytes);
         outputStream.flush();

         socket.close();
      }
   }
}

Lato Client:

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

public class FileClient {
   public static void main(String[] args) throws IOException {
      Socket socket = new Socket("localhost", 8080);

      BufferedReader reader = new BufferedReader(
          new InputStreamReader(socket.getInputStream()));
      PrintWriter writer = new PrintWriter(socket.getOutputStream());

      System.out.print("Enter file name: ");
      Scanner scanner = new Scanner(System.in);
      String fileName = scanner.nextLine();

      writer.println(fileName);
      writer.flush();

      String response = reader.readLine();
      if (response.equals("File not found")) {
         System.out.println("File not found on server");
         return;
      }

      FileOutputStream fileOutputStream = new FileOutputStream(fileName);
      InputStream inputStream = socket.getInputStream();

      byte[] buffer = new byte[4096];
      int bytesRead;
      while ((bytesRead = inputStream.read(buffer)) != -1) {
         fileOutputStream.write(buffer, 0, bytesRead);
      }
      fileOutputStream.close();

      System.out.println("File received");
   }
}

Pubblicato da Carlo Contardi

Carlo Contardi, docente di informatica e sviluppatore Full Stack, condivide la sua passione per la programmazione e l’informatica attraverso il suo blog Space Coding. Offre preziosi consigli e soluzioni pratiche a chi vuole imparare a programmare o migliorare le proprie abilità. 🚀👨‍💻

Translate »