IMPORTANT: Per accedir als fitxer de subversion: http://acacha.org/svn (sense password). Poc a poc s'aniran migrant els enllaços. Encara però funciona el subversion de la farga però no se sap fins quan... (usuari: prova i la paraula de pas 123456)

Classes

java.net.Socket

java.net.Socket és la clase principal per a la programació en xarxes amb Java.

Aquesta classe implementa el que es coneix com un socket client o simplement com a socket. Un socket representa el punt final d'una comunicació entre dos màquines.

La feina real d'un socket es realitzar per una instància de la classe SocketImpl class. Una aplicació, canviant la factoria que crear la implementació del socket concreta, es pot configurar sense necessitat de tornar a escriure el codi.

Recursos:

SocketImpl

La clase abstracta SocketImpl és una superclase comuna a totes les clases que implementen sockets. S'utilitzar tant per crear sockets client com sockets de servidor.

Un socket senzill implementa els mètodes descrits per aquesta classe tal qual, sense intentar passar a través d'un Firewall o Proxy.

Recursos:

java.net.ServerSocket

java.net. SSLSocket

Datagrames (UDP)

java.net.DatagramSocket

Aquesta clase Java representa un socket que permet enviar paquets de tipus datagrama, típicament utilitzant el protocol UDP.

Quan sigui possible, un objecte acabat de crear de tipus DatagramSocket té l'opció SO_BROADCAST activada i per tant pot rebre datagrames de broadcast.

Exemple:

DatagramSocket s = new DatagramSocket(null); 
s.bind(new InetSocketAddress(8888)); 

És equivalent a.

DatagramSocket s = new DatagramSocket(8888); 

Els dos casos crearan un DatagramSocket capaç de rebre broadcasts UDP al port 8888

DatagramSocket java.net.DatagramPacket

java.net.DatagramPacket

Els paquets de tipus datagrama s'utilitzen per implementar un servei de tipus sense connexió. Cada missatge s'encamina de forma independent a la resta i nomes s'utilitza la informació que porta inclosa el propi missatge. Múltiples paquets enviats del mateix tipus d'una màquina a un altre poden ser encaminats de forma diferentm i poden arrivar en diferent ordre (és a dir en diferent ordre respecte a l'ordre de sortida). A més no es garateix l'entrega del paquet.

DatagramPacket java.net.DatagramPacket

Estructura típica del codi

Servidor

Primer cal declarar el socket:

 protected DatagramSocket socket = null;

Típicament es pot definir com un atribut de la clase servidor.

Fora del bucle infinit (si implementem el servidor com a un servei) cal crear el socket:

socket = new DatagramSocket(4445);

A l'exemple creem un socket UDP al port 4445. El socket s'ha de crear una sola vegada per tant es pot crear al constructor de la clase servidor.

Ara es tracta d'estar rebent continuament paquets de tipus datagrama pel port 4445, per tant dins d'un while infinit:

 while (1) {
            try {
                byte[] buf = new byte[256];
 
                // receive request
                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
 
                //Aquí el codi amb el que treballarem el packet rebut
                // Com es poden obtenir dades:
                // IP:   InetAddress address = packet.getAddress();
                // Port: int port = packet.getPort();
                // Dades: Exemple String: String received = new String(packet.getData(), 0, packet.getLength()); 
        }
        socket.close();
 

On

 byte[] buf = new byte[256];
 

És la mida màxima del paquet en bytes que esperem. Ha de ser prou gran per que no es tallin els nostres paquets.I:

                DatagramPacket packet = new DatagramPacket(buf, buf.length);
                socket.receive(packet);
 

És la recepció del paquet.

IMPORTANT: Observeu la importància d'alliberar recursos i tancar el socket amb close!

Client

Vegem un exemple d'una sola execució:

    public static void main(String[] args) throws IOException {
 
        DatagramSocket socket = new DatagramSocket();
 
        // send request
        byte[] buf = new byte[256];
        String stringToConvert = "Missatge de prova";        
        buf = stringToConvert.getBytes();
        InetAddress address = new InetAddress ("192.168.0.5")
        DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 4445);
        socket.send(packet);
  
        socket.close();
    }
}

IMPORTANT: Feu coincidir la mida dels dos buffers tal al costat del client com del servidor per evitar problemes.

Tipus de sockets

Orientats a connexió

Datagrames

Certes aplicaciones no necessiten la fiabilitat d'una connexió punt a punt que proveix un canal TCP. Al contrari per aquelles aplicacions que no sigui imprescindible o en xarxes d'una alta fiabilitat de per si pot ser interessant utilitzar UDP, ja que és un protocol de transmisió de dades molt més ràpid que TCP.

El protocol UDP proveix una forma de comunicació on les aplicacions envien paquets de dades, anomenats datagrames. Un datagrama és un missatge auto-contingut i independent del qual no es pot garantir ni l'arribada, ni l'ordre d'arribada ni tant sol el seu contingut.

El paquet java.net proveix les classes DatagramPacket i DatagramSocket proveixen d'un sistema per a crear datagrames per a qualsevol sistema (recordeu que Java és multiplataforma) utilitzant UDP

IMPORTANT: La implementació concreta del datagrama o socket UDP depén del sistema operatiu on corre l'aplicació Java, en tot cas el codi no cal canviar-lo per adaptar-lo a cada tipus de sistema operatiu

Exemples

Socket de servidor simple

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;


public class MyServer {
 
 public static void main(String[] args){
  ServerSocket serverSocket = null;
  Socket socket = null;
  DataInputStream dataInputStream = null;
  DataOutputStream dataOutputStream = null;
  
  try {
   serverSocket = new ServerSocket(8888);
   System.out.println("Listening :8888");
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
  
  while(true){
   try {
    socket = serverSocket.accept();
    dataInputStream = new DataInputStream(socket.getInputStream());
    dataOutputStream = new DataOutputStream(socket.getOutputStream());
    System.out.println("ip: " + socket.getInetAddress());
    System.out.println("message: " + dataInputStream.readUTF());
    dataOutputStream.writeUTF("Hello!");
   } catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
   }
   finally{
    if( socket!= null){
     try {
      socket.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    
    if( dataInputStream!= null){
     try {
      dataInputStream.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
    
    if( dataOutputStream!= null){
     try {
      dataOutputStream.close();
     } catch (IOException e) {
      // TODO Auto-generated catch block
      e.printStackTrace();
     }
    }
   }
  }
 }
}

Exemple amb UDP. DatagramSocket

TODO: Enviar un número de forma incremental (incrementar cada segon).

Que cal?

     byte [] bytes = ByteBuffer.allocate(4).putInt(17291729).array();

Recursos:

Vegeu també

Enllaços externs