Recherche…


Syntaxe

  • nouveau Socket ("localhost", 1234); // Se connecte à un serveur à l'adresse "localhost" et au port 1234
  • nouveau SocketServer ("localhost", 1234); // Crée un serveur de socket capable d’écouter les nouvelles sockets à l’adresse localhost et au port 1234
  • socketServer.accept (); // Accepte un nouvel objet Socket qui peut être utilisé pour communiquer avec le client

Communication de base entre le client et le serveur à l'aide d'un socket

Serveur: démarrer et attendre les connexions entrantes

//Open a listening "ServerSocket" on port 1234.
ServerSocket serverSocket = new ServerSocket(1234); 

while (true) {
    // Wait for a client connection.
    // Once a client connected, we get a "Socket" object
    // that can be used to send and receive messages to/from the newly 
    // connected client
    Socket clientSocket = serverSocket.accept();            
    
    // Here we'll add the code to handle one specific client.
}

Serveur: Gestion des clients

Nous traiterons chaque client dans un thread séparé afin que plusieurs clients puissent interagir avec le serveur en même temps. Cette technique fonctionne bien tant que le nombre de clients est faible (<< 1000 clients, selon l'architecture du système d'exploitation et la charge attendue de chaque thread).

new Thread(() -> {
    // Get the socket's InputStream, to read bytes from the socket
    InputStream in = clientSocket.getInputStream();
    // wrap the InputStream in a reader so you can read a String instead of bytes
    BufferedReader reader = new BufferedReader(
            new InputStreamReader(in, StandardCharsets.UTF_8));
    // Read text from the socket and print line by line
    String line;
    while ((line = reader.readLine()) != null) {
        System.out.println(line);
    }
    }).start();

Client: Connectez-vous au serveur et envoyez un message

// 127.0.0.1 is the address of the server (this is the localhost address; i.e.
// the address of our own machine)
// 1234 is the port that the server will be listening on
Socket socket = new Socket("127.0.0.1", 1234);

// Write a string into the socket, and flush the buffer
OutputStream outStream = socket.getOutputStream();
PrintWriter writer = new PrintWriter(
        new OutputStreamWriter(outStream, StandardCharsets.UTF_8));
writer.println("Hello world!");
writer.flush();

Fermeture des sockets et gestion des exceptions

Les exemples ci-dessus ont laissé de côté certaines choses pour les rendre plus lisibles.

  1. Tout comme les fichiers et les autres ressources externes, il est important de dire au système d’exploitation lorsque nous en avons fini avec eux. Lorsque vous avez terminé avec un socket, appelez socket.close() pour le fermer correctement.

  2. Les sockets gèrent les opérations d'entrée / sortie (E / S) qui dépendent de divers facteurs externes. Par exemple, si l'autre côté se déconnecte soudainement? Que se passe-t-il s'il y a une erreur de réseau? Ces choses sont hors de notre contrôle. C'est la raison pour laquelle de nombreuses opérations de socket peuvent générer des exceptions, en particulier IOException .

Un code plus complet pour le client serait donc quelque chose comme ceci:

 // "try-with-resources" will close the socket once we leave its scope
 try (Socket socket = new Socket("127.0.0.1", 1234)) {
     OutputStream outStream = socket.getOutputStream();
     PrintWriter writer = new PrintWriter(
             new OutputStreamWriter(outStream, StandardCharsets.UTF_8));
     writer.println("Hello world!");
     writer.flush();
 } catch (IOException e) {
     //Handle the error
 }

Serveur et client de base - exemples complets

Serveur:

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Server {
    public static void main(String args[]) {
        try (ServerSocket serverSocket = new ServerSocket(1234)) {
            while (true) {
                // Wait for a client connection.
                Socket clientSocket = serverSocket.accept();
                
                // Create and start a thread to handle the new client
                new Thread(() -> {
                    try {
                        // Get the socket's InputStream, to read bytes 
                        // from the socket
                        InputStream in = clientSocket.getInputStream();
                        // wrap the InputStream in a reader so you can 
                        // read a String instead of bytes
                        BufferedReader reader = new BufferedReader(
                             new InputStreamReader(in, StandardCharsets.UTF_8));
                        // Read from the socket and print line by line
                        String line;
                        while ((line = reader.readLine()) != null) {
                            System.out.println(line);
                        }
                    }
                    catch (IOException e) {
                        e.printStackTrace();
                    } finally {
                        // This finally block ensures the socket is closed.
                        // A try-with-resources block cannot be used because
                        // the socket is passed into a thread, so it isn't 
                        // created and closed in the same block
                        try {
                            clientSocket.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                }).start();
            }
        }
        catch (IOException e) {
            e.printStackTrace();
        }

    }
}

Client:

import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.charset.StandardCharsets;

public class Client {
    public static void main(String args[]) {
        try (Socket socket = new Socket("127.0.0.1", 1234)) {
            // We'll reach this code once we've connected to the server
            
            // Write a string into the socket, and flush the buffer
            OutputStream outStream = socket.getOutputStream();
            PrintWriter writer = new PrintWriter(
                    new OutputStreamWriter(outStream, StandardCharsets.UTF_8));
            writer.println("Hello world!");
            writer.flush();
        } catch (IOException e) {
            // Exception should be handled.
            e.printStackTrace();
        }
    }
}

Chargement de DOSSIERORE et de KeyStore depuis InputStream

public class TrustLoader {
    
    public static void main(String args[]) {
        try {
                //Gets the inputstream of a a trust store file under ssl/rpgrenadesClient.jks
                //This path refers to the ssl folder in the jar file, in a jar file in the same directory
                //as this jar file, or a different directory in the same directory as the jar file
                InputStream stream = TrustLoader.class.getResourceAsStream("/ssl/rpgrenadesClient.jks");
                //Both trustStores and keyStores are represented by the KeyStore object
                KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                //The password for the trustStore
                char[] trustStorePassword = "password".toCharArray();
                //This loads the trust store into the object
                trustStore.load(stream, trustStorePassword);
                
                //This is defining the SSLContext so the trust store will be used
                //Getting default SSLContext to edit.
                SSLContext context = SSLContext.getInstance("SSL");
                //TrustMangers hold trust stores, more than one can be added
                TrustManagerFactory factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
                //Adds the truststore to the factory
                factory.init(trustStore);
                //This is passed to the SSLContext init method
                TrustManager[] managers = factory.getTrustManagers();
                context.init(null, managers, null);
                //Sets our new SSLContext to be used.
                SSLContext.setDefault(context);
            } catch (KeyStoreException | IOException | NoSuchAlgorithmException 
                    | CertificateException | KeyManagementException ex) {
                //Handle error
                ex.printStackTrace();
            }
        
    }
}

Utiliser un KeyStore fonctionne de la même manière, sauf remplacer n'importe quel mot Trust dans un nom d'objet par Key . De plus, le KeyManager[] doit être transmis au premier argument de SSLContext.init . C'est SSLContext.init(keyMangers, trustMangers, null)

Exemple de socket - lecture d'une page Web à l'aide d'un socket simple

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

public class Main {

    public static void main(String[] args) throws IOException {//We don't handle Exceptions in this example 
        //Open a socket to stackoverflow.com, port 80
        Socket socket = new Socket("stackoverflow.com",80);

        //Prepare input, output stream before sending request
        OutputStream outStream = socket.getOutputStream();
        InputStream inStream = socket.getInputStream();
        BufferedReader reader = new BufferedReader(new InputStreamReader(inStream));
        PrintWriter writer = new PrintWriter(new BufferedOutputStream(outStream));

        //Send a basic HTTP header
        writer.print("GET / HTTP/1.1\nHost:stackoverflow.com\n\n");
        writer.flush();

        //Read the response
        System.out.println(readFully(reader));

        //Close the socket
        socket.close();
    }
    
    private static String readFully(Reader in) {
        StringBuilder sb = new StringBuilder();
        int BUFFER_SIZE=1024;
        char[] buffer = new char[BUFFER_SIZE]; // or some other size, 
        int charsRead = 0;
        while ( (charsRead  = rd.read(buffer, 0, BUFFER_SIZE)) != -1) {
          sb.append(buffer, 0, charsRead);
        }
    }
}

Vous devriez obtenir une réponse commençant par HTTP/1.1 200 OK , qui indique une réponse HTTP normale, suivie du reste de l'en-tête HTTP, suivie de la page Web brute au format HTML.

Notez que la méthode readFully() est importante pour éviter une exception EOF prématurée. La dernière ligne de la page Web manque peut-être un retour, pour signaler la fin de la ligne, alors readLine() se plaindra, donc il faut le lire à la main ou utiliser des méthodes utilitaires d' Apache commons-io IOUtils

Cet exemple se veut une simple démonstration de connexion à une ressource existante à l'aide d'un socket, ce n'est pas un moyen pratique d'accéder aux pages Web. Si vous devez accéder à une page Web à l'aide de Java, il est préférable d'utiliser une bibliothèque de clients HTTP existante, telle que le client HTTP d'Apache ou le client HTTP de Google.

Communication basique client / serveur via UDP (Datagram)

Client.java

import java.io.*;
import java.net.*;
    
public class Client{
    public static void main(String [] args) throws IOException{
        DatagramSocket clientSocket = new DatagramSocket(); 
        InetAddress address = InetAddress.getByName(args[0]);

        String ex = "Hello, World!";
        byte[] buf = ex.getBytes();

        DatagramPacket packet = new DatagramPacket(buf,buf.length, address, 4160); 
        clientSocket.send(packet);
    }
}

Dans ce cas, on passe l'adresse du serveur, via un argument ( args[0] ). Le port que nous utilisons est 4160.

Server.java

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

public class Server{
    public static void main(String [] args) throws IOException{
        DatagramSocket serverSocket = new DatagramSocket(4160);

        byte[] rbuf = new byte[256];
        DatagramPacket packet = new DatagramPacket(rbuf, rbuf.length);        
        serverSocket.receive(packet);
        String response = new String(packet.getData());
        System.out.println("Response: " + response);
    }
}

Du côté du serveur, déclarez un DatagramSocket sur le même port auquel nous avons envoyé notre message (4160) et attendez une réponse.

Multicast

La multidiffusion est un type de socket de datagramme. Contrairement aux datagrammes classiques, la multidiffusion ne gère pas chaque client individuellement, mais l'envoie à une adresse IP et tous les clients abonnés recevront le message.

entrer la description de l'image ici

Exemple de code pour un côté serveur:

public class Server {
    
    private DatagramSocket serverSocket;
    
    private String ip;
    
    private int port;
    
    public Server(String ip, int port) throws SocketException, IOException{
        this.ip = ip;
        this.port = port;
        // socket used to send
        serverSocket = new DatagramSocket();
    }
    
    public void send() throws IOException{
        // make datagram packet
        byte[] message = ("Multicasting...").getBytes();
        DatagramPacket packet = new DatagramPacket(message, message.length, 
            InetAddress.getByName(ip), port);
        // send packet
        serverSocket.send(packet);
    }
    
    public void close(){
        serverSocket.close();
    }
}

Exemple de code pour un client:

public class Client {
    
    private MulticastSocket socket;
    
    public Client(String ip, int port) throws IOException {
        
        // important that this is a multicast socket
        socket = new MulticastSocket(port);
        
        // join by ip
        socket.joinGroup(InetAddress.getByName(ip));
    }
    
    public void printMessage() throws IOException{
        // make datagram packet to recieve
        byte[] message = new byte[256];
        DatagramPacket packet = new DatagramPacket(message, message.length);
        
        // recieve the packet
        socket.receive(packet);
        System.out.println(new String(packet.getData()));
    }
    
    public void close(){
        socket.close();
    }
}

Code pour exécuter le serveur:

public static void main(String[] args) {
    try {
        final String ip = args[0];
        final int port = Integer.parseInt(args[1]);
        Server server = new Server(ip, port);
        server.send();
        server.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

Code pour exécuter un client:

public static void main(String[] args) {
    try {
        final String ip = args[0];
        final int port = Integer.parseInt(args[1]);
        Client client = new Client(ip, port);
        client.printMessage();
        client.close();
    } catch (IOException ex) {
        ex.printStackTrace();
    }
}

Exécuter le client d'abord: le client doit s'abonner à l'IP avant de pouvoir commencer à recevoir des paquets. Si vous démarrez le serveur et appelez la méthode send() , puis créez un client (& appelez printMessage() ). Rien ne se passera car le client est connecté après l'envoi du message.

Désactivez temporairement la vérification SSL (à des fins de test)

Parfois, dans un environnement de développement ou de test, la chaîne de certificats SSL n'a peut-être pas encore été entièrement établie.

Pour continuer à développer et à tester, vous pouvez désactiver la vérification SSL par programme en installant un gestionnaire de confiance "fiable":

try {
   // Create a trust manager that does not validate certificate chains
   TrustManager[] trustAllCerts = new TrustManager[] {
      new X509TrustManager() {
       public X509Certificate[] getAcceptedIssuers() {
           return null;
       }
       public void checkClientTrusted(X509Certificate[] certs, String authType) {
       }
       public void checkServerTrusted(X509Certificate[] certs, String authType) {
       }
      }
   };

   // Install the all-trusting trust manager
   SSLContext sc = SSLContext.getInstance("SSL");
   sc.init(null, trustAllCerts, new java.security.SecureRandom());
   HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

   // Create all-trusting host name verifier
   HostnameVerifier allHostsValid = new HostnameVerifier() {
       public boolean verify(String hostname, SSLSession session) {
           return true;
       }
   };

   // Install the all-trusting host verifier
   HttpsURLConnection.setDefaultHostnameVerifier(allHostsValid);
} catch (NoSuchAlgorithmException | KeyManagementException e) {
    e.printStackTrace();
}

Télécharger un fichier en utilisant Channel

Si le fichier existe déjà, il sera écrasé!

String fileName     = "file.zip";                  // name of the file
String urlToGetFrom = "http://www.mywebsite.com/"; // URL to get it from
String pathToSaveTo = "C:\\Users\\user\\";         // where to put it

//If the file already exists, it will be overwritten!
  
//Opening OutputStream to the destination file
try (ReadableByteChannel rbc = 
      Channels.newChannel(new URL(urlToGetFrom + fileName).openStream()) ) {
    try ( FileChannel channel = 
        new FileOutputStream(pathToSaveTo + fileName).getChannel(); ) {
      channel.transferFrom(rbc, 0, Long.MAX_VALUE);
    }
    catch (FileNotFoundException e) { /* Output directory not found */ }
    catch (IOException e)           { /* File IO error */ }
}
catch (MalformedURLException e)     { /* URL is malformed */ }
catch (IOException e)               { /* IO error connecting to website */ }

Remarques

  • Ne laissez pas les blocs de capture vides!
  • En cas d'erreur, vérifiez si le fichier distant existe
  • Ceci est une opération de blocage, peut prendre beaucoup de temps avec des fichiers volumineux


Modified text is an extract of the original Stack Overflow Documentation
Sous licence CC BY-SA 3.0
Non affilié à Stack Overflow