Buscar..


Sintaxis

  • nuevo Socket ("localhost", 1234); // Se conecta a un servidor en la dirección "localhost" y el puerto 1234
  • nuevo SocketServer ("localhost", 1234); // Crea un servidor de socket que puede escuchar nuevos sockets en la dirección localhost y el puerto 1234
  • socketServer.accept (); // Acepta un nuevo objeto Socket que puede usarse para comunicarse con el cliente

Comunicación básica de cliente y servidor mediante un socket

Servidor: Iniciar y esperar las conexiones 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.
}

Servidor: Manejo de clientes.

Manejaremos cada cliente en un subproceso separado para que múltiples clientes puedan interactuar con el servidor al mismo tiempo. Esta técnica funciona bien siempre que el número de clientes sea bajo (<< 1000 clientes, según la arquitectura del sistema operativo y la carga esperada de cada subproceso).

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();

Cliente: Conectarse al servidor y enviar un mensaje.

// 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();

Cierre de enchufes y manejo de excepciones.

Los ejemplos anteriores dejaron algunas cosas para facilitar su lectura.

  1. Al igual que los archivos y otros recursos externos, es importante que le informemos al sistema operativo cuando hayamos terminado con ellos. Cuando hayamos terminado con un socket, llame a socket.close() para cerrarlo correctamente.

  2. Los sockets manejan las operaciones de E / S (entrada / salida) que dependen de una variedad de factores externos. Por ejemplo, ¿qué pasa si el otro lado se desconecta de repente? ¿Qué pasa si hay un error de red? Estas cosas están más allá de nuestro control. Esta es la razón por la que muchas operaciones de socket pueden generar excepciones, especialmente IOException .

Por lo tanto, un código más completo para el cliente sería algo como esto:

 // "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
 }

Servidor básico y cliente - ejemplos completos

Servidor:

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();
        }

    }
}

Cliente:

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();
        }
    }
}

Cargando TrustStore y KeyStore desde 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();
            }
        
    }
}

La iniciación de un Almacén de claves funciona de la misma manera, excepto que reemplaza cualquier palabra Trust en un nombre de objeto con Key . Además, la matriz KeyManager[] debe pasar al primer argumento de SSLContext.init . Eso es SSLContext.init(keyMangers, trustMangers, null)

Ejemplo de socket: leer una página web utilizando 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);
        }
    }
}

Debería obtener una respuesta que comience con HTTP/1.1 200 OK , que indica una respuesta HTTP normal, seguida del resto del encabezado HTTP, seguida de la página web sin procesar en formato HTML.

Tenga en cuenta que el método readFully() es importante para evitar una excepción prematura de EOF. A la última línea de la página web le puede faltar una devolución, para indicar el final de la línea, luego readLine() se quejará, por lo que uno debe leerla a mano o usar métodos de utilidad de Apache commons-io IOUtils

Este ejemplo pretende ser una simple demostración de conectarse a un recurso existente mediante un socket, no es una forma práctica de acceder a páginas web. Si necesita acceder a una página web utilizando Java, es mejor utilizar una biblioteca de cliente HTTP existente, como el Cliente HTTP de Apache o el Cliente HTTP de Google.

Comunicación básica cliente / servidor mediante UDP (datagrama)

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);
    }
}

En este caso, pasamos la dirección del servidor, a través de un argumento ( args[0] ). El puerto que estamos utilizando es 4160.

Servidor.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);
    }
}

En el lado del servidor, declare un DatagramSocket en el mismo puerto al que enviamos nuestro mensaje (4160) y espere una respuesta.

Multidifusión

La multidifusión es un tipo de Datagram Socket. A diferencia de los Datagramas normales, la Multidifusión no maneja cada cliente individualmente, en lugar de eso, lo envía a una dirección IP y todos los clientes suscritos recibirán el mensaje.

introduzca la descripción de la imagen aquí

Código de ejemplo para un servidor:

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();
    }
}

Código de ejemplo para un lado del cliente:

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();
    }
}

Código para ejecutar el servidor:

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();
    }
}

Código para ejecutar un cliente:

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();
    }
}

Primero ejecute el Cliente: El Cliente debe suscribirse a la IP antes de que pueda comenzar a recibir paquetes. Si inicia el servidor y llama al método send() , y luego printMessage() un cliente (& call printMessage() ). Nada ocurrirá porque el cliente se conectó después de que se envió el mensaje.

Deshabilite temporalmente la verificación SSL (para propósitos de prueba)

En ocasiones, en un entorno de desarrollo o prueba, es posible que la cadena de certificados SSL no esté completamente establecida (aún).

Para continuar con el desarrollo y las pruebas, puede desactivar la verificación SSL mediante programación instalando un administrador de confianza "confiable":

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();
}

Descargando un archivo usando el canal

Si el archivo ya existe, se sobrescribirá!

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 */ }

Notas

  • No dejes los bloques de captura vacíos!
  • En caso de error, compruebe si el archivo remoto existe
  • Esta es una operación de bloqueo, puede llevar mucho tiempo con archivos grandes


Modified text is an extract of the original Stack Overflow Documentation
Licenciado bajo CC BY-SA 3.0
No afiliado a Stack Overflow