2. SÒCOLS
Creació
• El paquet java.net proporciona una classe Socket.
• De forma addicional, java.net inclou la classe
ServerSocket.
• La classe ServerSocket implementa un sòcol que
facilita que els servidors puguin escoltar i acceptar
peticions de connexions de clients.
3. SÒCOLS
Model de comunicació amb Java
• El model de sòcols més senzill és:
① El servidor estableix un port i espera un cert temps (timeout
segons) a que el client estableixi la connexió.
② El client estableix una connexió amb la màquina host a través
del port que es designa en port#.
③ El client i el servidor es comuniquen amb manipuladors
InputStream i OutputStream.
4. SÒCOLS
Model de comunicació amb Java
Servidor
ServerSocket(port#,timeo Client
ut)
accept() Socket(host,port#)
OutputStream OutputStream
InputStream InputStream
close() close()
5. SÒCOLS
Apertura de sòcols
• Si estem programant un CLIENT, el sòcol s’obre..:
Socket elMeuClient;
elMeuClient = new Socket(“Màquina”, numeroPort);
Màquina és el nom de la màquina en la que estem intentant obrir
la connexió.
numeroPort és el port del servidor que està corrent sobre el que
ens volem connectar.
Per les aplicacions que desenvolupem, haurem de seleccionar un
port per sobre del 1023.
6. SÒCOLS
Apertura de sòcols
• En l’exemple anterior no s’utilizen excepcions. Ara
bé, és una bona opció si treballem amb sòcols.
Socket elMeuClient;
try {
elMeuClient = new Socket(“Màquina”, numeroPort);
} catch(IOException e) {
System.out.println(e);
}
9. SÒCOLS
Apertura de sòcols
• Si estem programant un SERVIDOR, la forma
d’apertura del sòcol és..:
Socket elMeuServei;
try {
elMeuServei = new ServerSocket(numeroPort);
} catch(IOException e) {
System.out.println(e);
}
11. SÒCOLS
Apertura de sòcols
• A l’hora de implementar un servidor també
necessitem crear un objecte socket des del
ServerSocket que estigui al cas de les potencials
connexions.
Socket SocketServei = null;
try {
SocketServei = elMeuServei.accept();
} catch(IOException e) {
System.out.println(e);
}
12. SÒCOLS
Apertura de sòcols
• Si volguéssim crear un sòcol servidor sobre el port
5776 que pugui contenir 100 connexions
d’entrada en la cua..:
try {
ServerSocket httpd = new ServerSocket (5776,
100);
} catch(IOException e) {
System.err.println(e);
}
13. SÒCOLS
Creació d’Streams d’Entrada
• En la part del CLIENT de l’aplicació, es pot utilitzar la
classe DataInputStream per crear un stream d’entrada
que estigui preparat per rebre totes les respostes que
el servidor li enviï.
DataInputStream entrada;
try {
entrada = new DataInputStream(elMeuClient.getInputStream() );
} catch(IOException e) {
System.out.println(e);
}
14. SÒCOLS
Creació d’Streams d’Entrada
• La classe DataInputStream permet la lectura de línies
de text i tipus de dades primitives de Java (read(),
readChar(), readInt(), readDouble() i readLine()).
DataInputStream entrada;
try {
entrada = new
DataInputStream(elMeuClient.getInputStream() );
} catch(IOException e) {
System.out.println(e);
}
15. SÒCOLS
Creació d’Streams d’Entrada
• En el costat del SERVIDOR, també utilitzarem
DataInputStream però, en aquest cas, per rebre les
entrades que es produeixin dels clients que s’hagin
connectat:
DataInputStream entrada;
try {
entrada = new
DataInputStream(socketServei.getInputStream() );
} catch(IOException e) {
System.out.println(e);
}
16. SÒCOLS
Creació d’Streams de Sortida
• En el costat del CLIENT, podem crear un stream de
sortida per enviar informació al sòcol del servidor
utilitzant les classes PrintStream o DataInputStream.
PrintStream sortida;
try {
sortida = new PrintStream(elMeuClient.getOutputStream()
);
} catch(IOException e) {
System.out.println(e);
}
17. SÒCOLS
Creació d’Streams de Sortida
• La classe PrintStream té mètodes per la representació
de totes les dades primitives de Java (write i println()).
• Per l’enviament de informació al servidor també podem
utilitzar DataOutputStream..:
DataOutputStream sortida;
try {
sortida = new DataOutputStream (elMeuClient.getOutputStream() );
} catch(IOException e) {
System.out.println(e);
}
18. SÒCOLS
Creació d’Streams de Sortida
• La classe DataOutputStream permet escriure qualsevol dels
tipus primitius de Java – escriuen un tipus de dada primitiva
en l’stream de sortida – (per exemple, writeBytes() ).
• En el costat del SERVIDOR, podem utilitzar PrintStream per
enviar informació al client..:
PrintStream sortida;
try {
sortida = new PrintStream (socketServei.getOutputStream() );
} catch(IOException e) {
System.out.println(e);
}
Alerta: També podríem utilitzar la
classe DataOutputStream
19. SÒCOLS
Tancament de Sòcols
• Sempre haurem de tancar els canals d’entrada i sortida que
s’hagin obert durant l’execució de l’aplicació.
• En la part del client..: • En la part del servidor..:
try { try {
sortida.close(); sortida.close();
entrada.close(); entrada.close();
elMeuClient.close(); socketServei.close();
} catch(IOException e) { elMeuServei.close();
System.out.println(e); } catch(IOException e) {
} System.out.println(e);
}
20. SÒCOLS
Tancament de Sòcols
• En la part del client..: • En la part del servidor..:
try { try {
sortida.close(); sortida.close();
entrada.close(); entrada.close();
elMeuClient.close(); socketServei.close();
} catch(IOException e) { elMeuServei.close();
System.out.println(e); } catch(IOException e) {
} System.out.println(e);
}
• Primer, s’han de tancar els streams relacionats amb un socket abans que
el propi socket
• Així evitem possibles errors d’escriptura/lectura sobre descriptors ja
tancats.
21. SÒCOLS
Programa Client
El programa client es
connecta a un servidor
indicant el nom de la
màquina i el número de port
en el que el servidor esta
instal·lat.
22. SÒCOLS
Programa Servidor
El programa servidor
s’instal·la en un port
determinat, a l’espera de
connexions, a les que
tractarà mitjançant un segon
sòcol.
23. SÒCOLS
Programa Servidor
• S’utilitza un objecte de la classe ServerSocket (skServidor) que
serveix per esperar les connexions en un port determinat
(PORT).
• S’utilitza un objecte de la classe Socket (skClient) que serveix
per gestionar una connexió amb cada client.
• Mitjançant un bucle for i la variable numCli es restringeix el
número de clients a 3. Per cada cop que en el port d’aquest
servidor aparegui un client, s’atén i s’incrementa el comptador.
24. SÒCOLS
Programa Servidor
• Per atendre als clients s’utilitza la primitiva accept() de la classe
ServerSocket – és una rutina que crea un nou Socket (skClient)
per atendre a un client que s’ha connectat a aquest servidor.
• S’associa al socket creat (skClient) un flux de sortida
DataOutputStream d’escriptura seqüencial en el que s’escriu el
missatge a enviar al client.
• El tractament de les excepcions és molt reduït en aquest
exemple, únicament es captura i s’imprimeix el missatge que
inclou l’excepció mitjançant getMessage().
26. SÒCOLS CLIENT – SERVIDOR
Orientat a connexió
• Estableix un camí virtual entre servidor i
client fiable.
No hi ha pèrdues de informació ni duplicats
La informació arriba en el mateix ordre en
que s’envia.
• El client obre una sessió en el servidor i
aquest guarda un estat del client.
27. SÒCOLS CLIENT – SERVIDOR
Orientat a connexió - Client
• Inicia la connexió amb el servidor.
• Especifica l’adreça IP i el port del procés
servidor.
• Defineix un sòcol per establir la connexió amb el
servidor.
Client
Sòcol
client
28. SÒCOLS CLIENT – SERVIDOR
Orientat a connexió - Servidor
• Ha d’estar en execució
• Ha d’haver creat un socket (1) per on rebre als
clients que connectin amb ell
• Espera a que algun client es connecti.
Sòcol 1
Client
Servidor
Sòcol
client
29. SÒCOLS CLIENT – SERVIDOR
Orientat a connexió - Connexió
Quan un client es connecta amb un servidor..:
• El servidor crea un nou sòcol (2) perquè el
procés servidor es comuniqui amb el client.
• Així, és possible que un servidor es comuniqui
amb varis clients.
Sòcol 1
Client
Bytes Servidor
Sòcol
client Sòcol 2
30. CLIENTS TCP
Classe Socket - Constructors
• Socket (InetAddress adreçaIP, int port)
• Socket (String NomHost, int port)
Crea un sòcol (socket) i el connecta amb el servidor indicat.
• Socket (InetAddress adreçaIP, int port, InetAddress AdreçaLocal, int
PortLocal)
• Socket (String NomHost, int port, InetAddress AdreçaLocal, int
PortLocal)
Crea un sòcol (socket) i el connecta amb el servidor indicat
vinculant-lo a una adreça IP i ports locals en concret.
31. CLIENTS TCP
Classe Socket - Alguns mètodes importants
InputStream getInputStream()
Proporciona un fluxe d’entrada per llegir del socket
OutputStream getOutputStream()
Proporciona un fluxe de sortida
close()
Tanca el sòcol
32. GESTIÓ DELS FLUXES
D’entrada
InputStream és la classe per tots els fluxos d’entrada en bytes.
Es pot llegir un byte: read() o un grup: read(byte[] b)
InputStreamReader converteix un flux d’entrada (en bytes) en un
flux de caràcters.
Es pot llegir un caràcter: read() o un grup: read(char[] text)
BufferedReader És un magatzem per un flux d’entrada de caràcters.
Té el mètode readLine() per llegir una línia de caràcters.
Exemple:
Buffer
BufferedReader entrada = new BufferedReader(new InputStreamReader(s.getInputStream()));
entrada.readLine();
33. CLIENTS TCP
Client TCP bàsic
Aquest client es connecta al servidor FTP (port 21) i visualitza la
primera línia que rep del servidor.
A continuació, tanca la connexió.
Quina sortida es genera? 220 Microsoft FTP Service
34. GESTIÓ DELS FLUXES
De sortida
OutputStream admet un flux de bytes
Es pot escriure un byte: write(int b) o un grup: write(byte[] b)
PrintWriter permet enviar text (caràcters)
Té mètodes que permeten escriure una línia de text: print(String s) i
println(String s)
Línies Bytes
Exemple:
PrintWriter sortida = new PrintWriter(s.getOutputStream());
sortida.print (“GET / HTTP /1.0” + “rn”);
35. CLIENTS TCP
Client TCP bàsic (2)
Envia una petició HTTP al servidor www.upv.es
Quina sortida es genera? HTTP/1.0 200 OK
36. SERVIDORS TCP
Classe ServerSocket - Constructors
ServerSocket (int port)
Obre un sòcol en el port indicat en mode d’escolta
Si port=0, llavors s’escull qualsevol port lliure
ServerSocket(int port, int backlog)
Obre un sòcol (socket) en el port indicat en mode
d’escolta
backlog indica la longitud màxima de la cua de
connexions a l’espera
Quan arriba una sol·licitud de connexió i la cua es troba
plena, es rebutjarà la connexió.
37. SERVIDORS TCP
Classe ServerSocket - Alguns mètodes importants
Socket accept ()
Accepta una connexió d’un client i retorna un socket associat a
ella
El procés es bloqueja fins que es realitza una connexió
El diàleg amb el client es fa pel nou socket
El ServerSocket pot atendre noves connexions
Socket close ()
Tanca el socket servidor
39. SERVIDORS TCP
Servidor TCP (2)
Servidor iteratiu: Atent contínuament a nous clients
A cadascun d’ells els enviaria una cadena amb el
seu número del cient i després tancarà el sòcol
40. CREACIÓ D’OBJECTES STREAM
Comunicació client / servidor
Servidor
• Un cop que el servidor ha creat un canal (socket) per escoltar, ja es pot
comunicar amb el client.
• Com que el servidor rebrà dades, associa un fluxe d’entrada de dades
(InputStream) a aquest canal.
InputStream soc_entrant;
.
.
eoc_entrant = sk.getInputStream()
• I un filtre (DataInputStream) que permet transformar la codificació de les
dades – per exemple, en UTF (Unicode Transfer Format) - i el transforma en
un String. DataInputStream dis;
.
.
dis = new dataInputStream(soc_entrant);
• En conseqüència, hem creat un fluxe d’entrada de dades. Ara bé, en podrem
crear dos : un d’entrada i un de sortida.
41. CREACIÓ D’OBJECTES STREAM
Comunicació client / servidor
Associem un fluxe d’entrada de dades al
canal de comunicació
Agafem el fluxe
d’entrada i apliquem
un filtre
I Codifiquem les dades en UTF i les
transformem en un string
42. CREACIÓ D’OBJECTES STREAM
Comunicació client / servidor
Client
• Un cop obert el socket, associem un fluxe de sortida (OutputStream) i
un filtre (DataOutputStream) que servirà per transformar un String a
UTF.
OutputStream soc_sortint;
DataOutputStream dos;
.
.
soc_sortint = sk.getOutputStream();
dos = new DataOutputStream (soc_sortint)
.
.
dos.writeUTF(miss)
43. CREACIÓ D’OBJECTES STREAM
Comunicació client / servidor
Associem un fluxe de
sortida i un filtre
Proporcionem un
fluxe de sortida
48. INTERACCIÓ CLIENT / SERVIDOR
Cicle de vida d’un sòcol TCP
L’aplicació client
Espera 30 segons CLOSED arrenca una connexió TCP
TIME_WAIT SYN_SENT
Rep el senyal de FI Rep el SYN & ACK
Envia l’ACK Envia l’ACK
FIN_WAIT_2 ESTABLISHED
Envia el senyal de
Rep l’ACK FIN_WAIT_1 finalització de l’espera
No envia res
Cicle de vida del client TCP
49. INTERACCIÓ CLIENT / SERVIDOR
Cicle de vida d’un sòcol TCP
L’aplicació servidor
Rep l’ACK CLOSED Crea un sòcol receptor
No envia res
TIME_WAIT LISTEN
Envia el FI Rep el SYN
Envia el SYN i l’ACK
CLOSE_WAIT SYN_RCVD
Rep l’ACK
Rep el FI ESTABLISHED No envia res
Envia l’ACK
Cicle de vida del servidor TCP
51. INTERACCIÓ SÒCOLS TCP
Excepcions
BindException: Es dóna quan s’intenta construir un sòcol
sobre un port en ús o si no es tenen privilegis per fer-ho.
ConnectException: Es dóna quan el host remot rebutja la
connexió
NoRouteToHostException: Es dóna quan ha expirat el temps
d’establiment de la connexió.
SocketException: Es dóna quan hi ha un error en el socket.
UnknownHostException: Es dóna si no troba la màquina
amb la que vol establir la connexió.
53. INTERACCIÓ CLIENT / SERVIDOR
Classe InetAddress
• Java proporciona la clase InetAddress per administar les
adreces IP i els dominis. Alguns dels mètodes que podem
trobar són els següents:
byte[] getAddress() ;
Retorna l’adreça IP d’un objecte InetAddress.
InetAddress getByName(String host) ;
Retorna un objecte InetAddress.
static InetAddressgetByAddress(byte[] adreça) ;
Introduim una adreça IP i ens retorna un obbjecte amb aquesta
adreça.
54. INTERACCIÓ CLIENT / SERVIDOR
Classe InetAddress (2)
• Java proporciona la clase InetAddress per administar les adreces IP
i els dominis. Alguns dels mètodes que podem trobar són els
següents:
static InetAddressgetByAddress(String host, byte[] addr) ;
Introduim una adreça IP i ens retorna un objecte amb aquesta adreça
i també guarda el host.
InetAdress getLocalHost() ;
Retorna un objecte amb l’adreça IP local de l’equip.
57. NO ORIENTAT A CONNEXIÓ
• Enviament de datagrames de grandària fixa.
• No és fiable, poden haver-hi pèrdues de informació i duplicats.
• La informació pot arribar en diferent ordre del que s’ha enviat.
DatagramPacket
Emissor Receptor
DatagramSocket DatagramSocket
58. NO ORIENTAT A CONNEXIÓ
• En UDP no hi ha handshaking.
• El remitent indica explícitament
l’adreça IP i el port d’origen i destí en
cada paquet.
• El recpetor ha d’extreure del paquet
rebut l’adreça IP i el port de l’emissor.
• Les dades transmeses poden arribar
fora d’ordre o, inclús, perdre’s.
59. NO ORIENTAT A CONNEXIÓ
Interacció CLIENT - SERVIDOR
Client
Servidor
60. NO ORIENTAT A CONNEXIÓ
Interacció CLIENT - SERVIDOR
Interacció
del usuari
SORTIDA: S’envia un ENTRADA: Es rep un
paquet (RECORDEU: paquet (RECORDEU:
En TCP, s’enviava un En TCP, es rebia un
flux de Bytes) Paquet flux de Bytes)
Paquet
Paquet
Envia
Rep
Paquet
UDP UDP
Client UDP Sòcol
Socket UDP
XARXA
61. CLASSE DatagramSocket
Constructors
• Un objecte java.DatagramSocket és un connector
mitjançant el qual enviarem i rebrem paquets UDP.
• Si volem utilitzar un DatagramSocket per rebre
paquets es necessita especificar el port.
• Al contrari, si és per enviar paquets, no cal
especificar aquest port.
62. CLASSE DatagramSocket
Serveis
public void send (DatagramPacket p)
Envia un datagrama a la màquina remota pel
sòcol (socket) associat.
public void receive (DatagramPacket p)
Rep un datagrama d’una altra màquina pel sòcol
(socket) associat.
63. CLASSE DatagramSocket
Comunicacions UDP: Constructors
DatagramPacket (byte buf[ ], int longitud)
Crea un datagrama UDP a partir d’aquest buffer i
amb aquesta longitud.
DatagramPacket (byte buf[ ], int longitud,
InetAddress Adreça_IP, int port)
Crea un datagrama UDP amb aquest buffer i
d’aquesta longitud per enviar-lo a l’adreça IP i el
port que s’indica.
64. CLASSE DatagramSocket
Comunicacions UDP: Constructors
DatagramSocket ( )
Crea un sòcol UDP que escolta en un port lliure.
DatagramPacket (int port)
Crea un sòcol UDP que escolta en aquest port.
65. CLASSE DatagramSocket
Exemple
DatagramSocket dsk1 = new DatagramSocket (123);
// Aquí utilitzem aquest DatagramSocket per rebre dades..
.
.
// Hem acabat; tanquem el socket
dsk1.close();
DatagramSocket dsk2 = new DatagramSocket ();
// Aquí l’utilitzem per transmetre dades
.
.
// Hem acabat; tanquem el socket
dsk2.close();
67. CLASSE DatagramSocket
Serveis
public void connect(InetAddress address, int port)
Connecta el socket a la màquina remota amb la @IP address i el
port port.
public void close ()
Tanca el canal de comunicació
public InetAddress getInetAddress()
Retorna la @IP de la màquina remota.
public int getPort()
Retorna el port de la màquina remota.
També hi ha dos crides per conèixer la @IP i el port local:
getLocalAddress() i getLocalPort().
68. ORIENTAT A CONNEXIÓ
Exercici 1: [Client – Servidor] Majúscules
• L’usuari (CLIENT) escriu una lína de text
• El programa (CLIENT) envia la línia al servidor
• El SERVIDOR rep la línia de text
• Posa en majúscules totes les lletres
• Envia la línia modificada al CLIENT
• El CLIENT rep la línia de text
• Mostra la línia de text
69. ORIENTAT A CONNEXIÓ
Exercici 1: [Client – Servidor] Majúscules
1) El client llegeix les línies de flux des
de l’entrada estàndard (flux
entradaDelUsuari) i les envia al
servidor mitjançant un sòcol (flux
dadesPelServidor)
2) El servidor llegeix les línies des del
sòcol
3) El servidor les converteix a
majúscules i les envia de tornada al
client
4) El client llegeix i mostra la línia
modificada des del sòcol (flux
RespostaDelServidor)
71. ORIENTAT A CONNEXIÓ
Exercici 1: [Client – Servidor] Majúscules
Creem el
flux entrant
Creem el socket
client per
connectar amb el
servidor
Creem el flux de sortida,
connectat al socket
72. ORIENTAT A CONNEXIÓ
Exercici 1: [Client – Servidor] Majúscules
Enviem la línia al
servidor
Llegim la línia que
arriba des del Creem el flux d’entrada,
servidor connectat al socket
73. ORIENTAT A CONNEXIÓ
Exercici 1: [Client – Servidor] Majúscules
Creem el sòcol de
benvinguda en el port 7777
Creem el sòcol per la
connexió de contacte
amb els clients
Creem el flux
d’entrada connectat
al socket
74. ORIENTAT A CONNEXIÓ
Exercici 1: [Client – Servidor] Majúscules
Creem el flux
de sortida Llegeix la línia
connectat al des del socket
socket
Escriu la línia
en el socket
76. NO ORIENTAT A CONNEXIÓ
Sockets UDP: Model client - servidor
I si volguéssim crear 2 mètodes que ens encapsulessin
una comunicació? UDP. Establiment, enviament o recepció
d’strings i tancament de la comunicació.
Missatge Missatge
Grandària Grandària
missatge missatge
Envia Rep
77. NO ORIENTAT A CONNEXIÓ
Sockets UDP: Model client - servidor
• El datagrama Paquet es pot comparar amb un sobre que conté
l’adreça de destí i la carta (les dades).
• El sòcol ElMeuSocket el podem comparar amb una bústia de
correus. Amb el mètode send estarem “dipositant el sobre en la
bústia”.
78. NO ORIENTAT A CONNEXIÓ
Sockets UDP: Model client - servidor
Definim el datagrama
amb les dades a
enviar (llargària,
adreça IP i port)
Enviem el datagrama al
“servidor”
• El datagrama Paquet es pot comparar amb un sobre que conté
l’adreça de destí i la carta (les dades).
• El sòcol ElMeuSocket el podem comparar amb una bústia de
correus. Amb el mètode send estarem “dipositant el sobre en la
bústia”.
79. NO ORIENTAT A CONNEXIÓ
Sockets UDP: Model client - servidor
• Un cop hem definit els objectes DatagramSocket i DatagramPacket ja
podem rebre (mètode receive) la informació.
• Amb el mètode getData recuperarem les dades; aquesta acció és similar a
obrir el sobre i treure la carta.
80. NO ORIENTAT A CONNEXIÓ
Sockets UDP: Model client - servidor
Definim el socket de
datagrama en el port
14000
Definim l’espai per
rebre els
datagrames
Rebem el datagrama
• Un cop hem definit els objectes DatagramSocket i DatagramPacket ja
podem rebre (mètode receive) la informació.
• Amb el mètode getData recuperarem les dades; aquesta acció és similar a
obrir el sobre i treure la carta.
81. NO ORIENTAT A CONNEXIÓ
Exercici 1Bis: [Client – Servidor] Majúscules
Definim el flux entrant
Definim el socket client
Traduïm el localhost a IP
mitjançant DNS
82. NO ORIENTAT A CONNEXIÓ
Exercici 1Bis: [Client – Servidor] Majúscules
Creem el datagrama amb les dades
a enviar (llargària, adreça IP i port)
Enviem el datagrama al servidor
Llegim el datagrama que
ens ha enviat el servidor
83. NO ORIENTAT A CONNEXIÓ
Exercici 1Bis: [Client – Servidor] Majúscules
Definim un socket de
datagrama en el port
9876
Definim l’espai
per rebre el
datagrama
Rebem el
datagrama
84. NO ORIENTAT A CONNEXIÓ
Exercici 1Bis: [Client – Servidor] Majúscules
Obtenim l’adreça IP i
el port del client
Creo el datagrama a
enviar al client
Envio el datagrama
mitjançant el socket
Finalitza el cos del While,
torna al seu inici i espera un
altre datagrama