bytes.cat

La wiki d'FP d'informàtica

Eines de l'usuari

Eines del lloc


Barra lateral

ASIX Administració de Sistemes Informàtics i Xarxes
Tots els mòduls del cicle
MP01 Implantació de sistemes operatius
Totes les UFs del modul
MP02 Gestió de bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Fonaments de maquinari
Totes les UFs del modul
MP06 Administració de sistemes operatius
Totes les UFs del modul
MP07 Planificació i administració de xarxes
Totes les UFs del modul
MP08 Serveis de xarxa i Internet
Totes les UFs del modul
MP09 Implantació d'aplicacions web
Totes les UFs del modul
MP10 Administració de sistemes gestors de bases de dades
Totes les UFs del modul
MP11 Seguretat i alta disponibilitat
Totes les UFs del modul
MP12 Formació i orientació laboral
Totes les UFs del modul
MP13 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP14 Projecte
Totes les UFs del modul
DAM Desenvolupament d’aplicacions multiplataforma
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació bàsica
Totes les UFs del modul
MP04 Llenguatges de marques i sistemes de gestió d'informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Accés a dades
Totes les UFs del modul
MP07 Desenvolupament d’interfícies
Totes les UFs del modul
MP08 Programació multimèdia i dispositius mòbils
Totes les UFs del modul
MP09 Programació de serveis i processos
Totes les UFs del modul
MP10 Sistemes de gestió empresarial
Totes les UFs del modul
MP11 Formació i orientació laboral
Totes les UFs del modul
MP12 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP13 Projecte de síntesi
Totes les UFs del modul
MPDual Mòdul Dual / Projecte
DAW Desenvolupament d’aplicacions web
Tots els mòduls del cicle
MP01 Sistemes informàtics
Totes les UFs del modul
MP02 Bases de dades
Totes les UFs del modul
MP03 Programació
Totes les UFs del modul
MP04 Llenguatge de marques i sistemes de gestió d’informació
Totes les UFs del modul
MP05 Entorns de desenvolupament
Totes les UFs del modul
MP06 Desenvolupament web en entorn client
Totes les UFs del modul
MP07 Desenvolupament web en entorn servidor
Totes les UFs del modul
MP08 Desplegament d'aplicacions web
Totes les UFs del modul
MP09 Disseny d'interfícies web
Totes les UFs del modul
MP10 Formació i Orientació Laboral
Totes les UFs del modul
MP11 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP12 Projecte de síntesi
Totes les UFs del modul
SMX Sistemes Microinformàtics i Xarxes
Tots els mòduls del cicle
MP01 Muntatge i manteniment d’equips
Totes les UFs del modul
MP02 Sistemes Operatius Monolloc
Totes les UFs del modul
MP03 Aplicacions ofimàtiques
Totes les UFs del modul
MP04 Sistemes operatius en xarxa
Totes les UFs del modul
MP05 Xarxes locals
Totes les UFs del modul
MP06 Seguretat informàtica
Totes les UFs del modul
MP07 Serveis de xarxa
Totes les UFs del modul
MP08 Aplicacions Web
Totes les UFs del modul
MP09 Formació i Orientació Laboral
Totes les UFs del modul
MP10 Empresa i iniciativa emprenedora
Totes les UFs del modul
MP11 Anglès
Totes les UFs del modul
MP12 Síntesi
Totes les UFs del modul
CETI Ciberseguretat en Entorns de les Tecnologies de la Informació
Tots els mòduls del cicle
CiberOT Ciberseguretat en Entorns d'Operació
Tots els mòduls del cicle
websockets_java

WebSockets a Java


Exemples

websockets_-_exemple_java.zip

websockets_-_exemple_android.zip

WebSockets

Tradicionalment cada aplicació s’ha implementat la comunicació per sockets

Actualment hi ha un protocol estàndard: WebSockets que implementa la comunicació amb sockets TCP i facilita el desenvolupament d’aplicacions que comuniquen diversos clients a través d’un servidor.

- Faciliten el desenvolupament d’apps que es comuniquen sense bloquejos.

- Funcionen per events, no cal esperar una lectura o escriptura.

- Poden funcionar amb ports estàndard a través del web.

WebSockets, llibreria websockets

Com que Java no els implementa directament, cal utilitzar alguna llibreria que ho faci. N’hi ha vàries, l’exemple fa servir:

- Java WebSockets (també a Github)

Necessitem les següents llibreries:

- Java-WebSocket-1.5.3.jar

- slf4j-api-2.0.3.jar

- slf4j-simple-2.0.3.jar

WebSockets, iniciar i tancar la connexió

Per crear un servidor de WebSockets cal extendre la classe ‘WebSocketServer’ i definir les funcions d’events

java.lang.System.setProperty("jdk.tls.client.protocols", 
                             "TLSv1,TLSv1.1,TLSv1.2");
 
WsServidor socket = new WsServidor(port);
socket.start();
System.out.println("WsServidor funciona al port: " + socket.getPort());
 
// Lògica del programa Servidor …
 
if (socket != null) socket.stop(1000);

Per crear un client de WebSockets cal extendre la classe ‘WebSocketClient’ i definir les funcions d’events

int port = 8888;
String host = "localhost";
String location = "ws://" + host + ":" + port;
try {
    client = new WsClient(new URI(location), 
                          (Draft) new Draft_6455());
    client.connect();
} catch (URISyntaxException e) {
    e.printStackTrace();
    System.out.println("Error: " + location 
           + " no és una direcció URI de WebSocket vàlida");
}
// Lògica del programa Servidor …
if (socket != null) socket.close();

WebSockets, funció ‘onMessage’ al servidor

Quan el servidor rep un missatge, executa la funció ‘onMessage’ i ens diu quin client l’ha enviat a través de ‘conn’. Pot rebre un “String” o un “ByteBuffer”

@Override
public void onMessage(WebSocket conn, String message) {
  broadcast(message);
  conn.send("Missatge enviat");
}
@Override
public void onMessage(WebSocket conn, ByteBuffer message) {
}

La funció ‘broadcast’ envia un missatge a tots els clients connectats ‘conn.send’ envia un missatge al client que ens ha enviat ‘message’

WebSockets, funció ‘onMessage’ al client

Quan el client rep un missatge, executa la funció ‘onMessage’ amb el missatge. Pot rebre un ‘String’ o un ‘ByteBuffer’

@Override
public void onMessage(WebSocket conn, String message) {
  conn.send("Missatge enviat");
}
@Override
public void onMessage(WebSocket conn, ByteBuffer message) {
}

WebSockets, serialitzar objecte a bytes

Cal tenir en compte que es poden enviar missatges en forma de ‘byte[]’ i per tant es poden enviar objectes serialitzats

També cal preveure que els missatges serialitzats no són compatibles si les versions de Java són diferents (per exemple entre Android i Java)

L'objecte ha de implementar Serialize

    public static byte[] objToBytes (Object obj) {
       byte[] result = null;
       try {
           // Transforma l'objecte a bytes[]
           ByteArrayOutputStream bos = new ByteArrayOutputStream();
           ObjectOutputStream oos = new ObjectOutputStream(bos);
           oos.writeObject(obj);
           oos.flush();
           result = bos.toByteArray();
       } catch (IOException e) { e.printStackTrace(); }
       return result;
   }

WebSockets, restaurar ByteBuffer a Objecte

Després caldrà fer un 'cast' a la classe de l'objecte en concret

public static Object bytesToObject (ByteBuffer arr) {
       Object result = null;
       try {
           // Transforma el ByteBuffer en byte[]
           byte[] bytesArray = new byte[arr.remaining()];
           arr.get(bytesArray, 0, bytesArray.length);
 
           // Transforma l'array de bytes en objecte
           ByteArrayInputStream in = new ByteArrayInputStream(bytesArray);
           ObjectInputStream is = new ObjectInputStream(in);
           return is.readObject();
 
       } catch (ClassNotFoundException e) { e.printStackTrace();
       } catch (UnsupportedEncodingException e) { e.printStackTrace();
       } catch (IOException e) { e.printStackTrace(); }
       return result;
   }

Exemple

WsClient.java

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Scanner;
 
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.exceptions.WebsocketNotConnectedException;
import org.java_websocket.handshake.ServerHandshake;
 
// Compilar amb:
// javac -cp "lib/*:." WsClient.java
// java -cp "lib/*:." WsClient
 
public class WsClient  extends WebSocketClient {
 
    private boolean running = true;
    private static Scanner sc = new Scanner(System.in);
 
    public static void main(String[] args) {
        int port = 8888;
        String host = "localhost";
        String location = "ws://" + host + ":" + port;
        String text = "";
 
        WsClient client = connecta(location);
 
        while (client.running) {
            text = sc.nextLine();
 
            try {
                client.send(text);
            } catch (WebsocketNotConnectedException e) {
                System.out.println("Connexió perduda, reconnectant ...");
                client = connecta(location);
            }            
 
            if (text.compareTo("exit") == 0) {
                client.running = false;
            }
        }
 
        if (client != null) { client.close(); }
    }
 
    public WsClient (URI uri, Draft draft) {
        super (uri, draft);
    }
 
    @Override
    public void onMessage(String message) {
        System.out.println("Has rebut un missatge: " + message);
        if (message.compareTo("exit") == 0) {
            System.out.println("El servidor s'ha aturat");
        }
    }
 
    @Override
    public void onOpen(ServerHandshake handshake) {
        System.out.println("T'has connectat a: " + getURI());
        System.out.println("list per veure la llista de ids");
        System.out.println("to(id)missatge per enviar missatges privats");
    }
 
    @Override
    public void onClose(int code, String reason, boolean remote) {
        System.out.println("T'has desconnectat de: " + getURI());
    }
 
    @Override
    public void onError(Exception ex) {
        System.out.println("Error amb la connexió del socket");
    }
 
    static public WsClient connecta (String location) {
        WsClient client = null;
 
        try {
            client = new WsClient(new URI(location), (Draft) new Draft_6455());
            client.connect();
        } catch (URISyntaxException e) { 
            e.printStackTrace(); 
            System.out.println("Error: " + location + " no és una direcció URI de WebSocket vàlida");
        }
 
        return client;
    }
}

WsGuiClient.java

import java.awt.Container;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowEvent;
import java.net.URI;
import java.net.URISyntaxException;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;
 
import org.java_websocket.client.WebSocketClient;
import org.java_websocket.drafts.Draft;
import org.java_websocket.drafts.Draft_6455;
import org.java_websocket.handshake.ServerHandshake;
 
public class WsGuiClient extends JFrame implements ActionListener {
 
  private final JTextField uriField;
  private final JButton connect;
  private final JButton close;
  private final JTextArea ta;
  private final JTextField chatField;
  private WebSocketClient cc;
 
    public static void main(String[] args) {
        int port = 8888;
        String location = "localhost";
 
        location = "ws://" + location + ":" + port;
        System.out.println("Default server url not specified: defaulting to \'" + location + "\'");
 
        new WsGuiClient(location);
    }
 
    public WsGuiClient(String defaultlocation) {
 
        super("WebSocket Chat Client");
        Container container = getContentPane();
        GridLayout layout = new GridLayout();
 
        layout.setColumns(1);
        layout.setRows(6);
        container.setLayout(layout);
 
        uriField = new JTextField();
        uriField.setText(defaultlocation);
        container.add(uriField);
 
        Container containerButtons = new Container();
        GridLayout layoutButtons = new GridLayout();
        layoutButtons.setColumns(2);
        layoutButtons.setRows(1);
        containerButtons.setLayout(layoutButtons);
 
        connect = new JButton("Connecta");
        connect.addActionListener(this);
        containerButtons.add(connect);
 
        close = new JButton("Desconnecta");
        close.addActionListener(this);
        close.setEnabled(false);
        containerButtons.add(close);
 
        container.add(containerButtons);
 
        JLabel labelArea = new JLabel("Consola:");
        container.add(labelArea);
 
        JScrollPane scroll = new JScrollPane();
        ta = new JTextArea();
        scroll.setViewportView(ta);
        container.add(scroll);
 
        JLabel labelEscriu = new JLabel("Escriu un missatge:");
        container.add(labelEscriu);
 
        chatField = new JTextField();
        chatField.setText("");
        chatField.addActionListener(this);
        container.add(chatField);
 
        java.awt.Dimension d = new java.awt.Dimension(300, 600);
        setPreferredSize(d);
        setSize(d);
 
        addWindowListener(new java.awt.event.WindowAdapter() {
          @Override
          public void windowClosing(WindowEvent e) {
            if (cc != null) {
              cc.close();
            }
            dispose();
          }
        });
 
        setLocationRelativeTo(null);
        setVisible(true);
    }
 
    public void actionPerformed(ActionEvent e) {
 
      if (e.getSource() == chatField) {
          if (cc != null) {
            cc.send(chatField.getText());
            chatField.setText("");
            chatField.requestFocus();
          }
      } else if (e.getSource() == connect) {
          try {
              cc = new WebSocketClient(new URI(uriField.getText()), (Draft) new Draft_6455()) {
                  @Override
                  public void onMessage(String message) {
                      ta.append("got: " + message + "\n");
                      ta.setCaretPosition(ta.getDocument().getLength());
                  }
 
                  @Override
                  public void onOpen(ServerHandshake handshake) {
                    String text = "T'has connectat a: " + getURI()
                              + "\nlist per veure la llista de ids"
                              + "\nto(id)missatge per enviar missatges privats";
 
                      ta.append(text);
                      ta.setCaretPosition(ta.getDocument().getLength());
                  }
 
                  @Override
                  public void onClose(int code, String reason, boolean remote) {
                      ta.append("T'has desconnectat de: " + getURI() + "\n");
                      ta.setCaretPosition(ta.getDocument().getLength());
                      connect.setEnabled(true);
                      uriField.setEditable(true);
                      close.setEnabled(false);
                  }
 
                  @Override
                  public void onError(Exception ex) {
                      ta.append("Error amb la connexió del socket\n");
                      ta.setCaretPosition(ta.getDocument().getLength());
                      connect.setEnabled(true);
                      uriField.setEditable(true);
                      close.setEnabled(false);
                  }
              };
 
              close.setEnabled(true);
              connect.setEnabled(false);
              uriField.setEditable(false);
              cc.connect();
            } catch (URISyntaxException ex) {
              ta.append(uriField.getText() + " no és una direcció URI de WebSocket vàlida\n");
            }
        } else if (e.getSource() == close) {
            cc.close();
        }
    }
}

WsServidor.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;
 
// Compilar amb:
// javac -cp "lib/*:." WsServidor.java
// java -cp "lib/*:." WsServidor
 
// Tutorials: http://tootallnate.github.io/Java-WebSocket/
 
public class WsServidor extends WebSocketServer {
 
    static BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
 
    public static void main(String[] args) throws InterruptedException, IOException {
        int port = 8888; 
        boolean running = true;
 
        // Deshabilitar SSLv3 per clients Android
        java.lang.System.setProperty("jdk.tls.client.protocols", "TLSv1,TLSv1.1,TLSv1.2");
 
        WsServidor socket = new WsServidor(port);
        socket.start();
        System.out.println("WsServidor funciona al port: " + socket.getPort());
 
        while (running) {
            String line = in.readLine();
            socket.broadcast(line);
            if (line.equals("exit")) {
                running = false;
            }
        }    
 
        System.out.println("Aturant WsServidor");
        socket.stop(1000);
    }
 
    public WsServidor(int port) throws UnknownHostException {
        super(new InetSocketAddress(port));
    }
 
    public WsServidor(InetSocketAddress address) {
        super(address);
    }
 
    @Override
    public void onOpen(WebSocket conn, ClientHandshake handshake) {
 
        // Saludem personalment al nou client
        conn.send("Benvingut a WsServer"); 
 
        // Enviem la direcció URI del nou client a tothom 
        broadcast("Nova connexió: " + handshake.getResourceDescriptor());
 
        // Mostrem per pantalla (servidor) la nova connexió
        String host = conn.getRemoteSocketAddress().getAddress().getHostAddress();
        System.out.println(host + " s'ha connectat");
    }
 
    @Override
    public void onClose(WebSocket conn, int code, String reason, boolean remote) {
 
        // Informem a tothom que el client s'ha desconnectat
        broadcast(conn + " s'ha desconnectat");
 
        // Mostrem per pantalla (servidor) la desconnexió
        System.out.println(conn + " s'ha desconnectat");
    }
 
    @Override
    public void onMessage(WebSocket conn, String message) {
 
        if (message.equalsIgnoreCase("list")) {
            // Enviar la llsita de connexions al client
            System.out.println("Llista de connexions:");
            String strList = "";
            for (WebSocket ws : this.getConnections()) {
                strList += " " + getConnectionId(ws);
 
            }
            conn.send(strList);
 
        } else if (message.contains("to(")) {
            // Missatge privat
 
            // Trobar el client amb aquest identificador
            String strDesti = message.substring(message.indexOf("(") + 1, message.indexOf(")"));
            WebSocket desti = null;
            for (WebSocket ws : this.getConnections()) {
                if (strDesti.compareTo(getConnectionId(ws)) == 0) {
                    desti = ws;
                    break;
                }                
            }
 
            // Enviar el missatge si s'ha trobat el client o retornar un error en cas contrari
            if (desti != null) {
                String idOrigen = getConnectionId(conn);
                String idDesti = getConnectionId(desti);
                desti.send("Missatge privat de " + idOrigen + ": " + message);
                conn.send("S'ha entregat el missatge privat a: " + idDesti);
                System.out.println("Missatge privat entre " + idOrigen + " i " + idDesti + ": " + message);
            } else {
                conn.send("No s'ha trobat el destí " + strDesti);
            }
 
        } else {
            // Enviem el missatge del client a tothom
            broadcast(getConnectionId(conn) + " ha dit: " + message);
 
            // Mostrem per pantalla (servidor) el missatge
            System.out.println("Broadcast de " + getConnectionId(conn) + ": " + message);
        }
    }
 
    @Override
    public void onMessage(WebSocket conn, ByteBuffer message) {
 
        // Enviem el missatge del client a tothom
        broadcast(message.array());
 
        // Mostrem per pantalla (servidor) el missatge
        System.out.println(conn + ": " + message);
    }
 
    @Override
    public void onError(WebSocket conn, Exception ex) {
        ex.printStackTrace();
    }
 
    @Override
    public void onStart() {
        // S'inicia el servidor
        System.out.println("Escriu 'exit' per aturar el servidor");
        setConnectionLostTimeout(0);
        setConnectionLostTimeout(100);
    }
 
    public String getConnectionId (WebSocket connection) {
        String name = connection.toString();
        return name.replaceAll("org.java_websocket.WebSocketImpl@", "").substring(0, 3);
    }
}
websockets_java.txt · Darrera modificació: 2022/11/24 08:29 per albert_palacios_jimenez