Diferencia entre revisiones de «Solucións as prácticas con Sockets UDP»
Ir a la navegación
Ir a la búsqueda
| (No se muestran 2 ediciones intermedias del mismo usuario) | |||
| Línea 208: | Línea 208: | ||
Pensas que para o envío de usuario e contrasinal é boa idea o uso de UDP? Ou sería mellor TCP? Por qué? | Pensas que para o envío de usuario e contrasinal é boa idea o uso de UDP? Ou sería mellor TCP? Por qué? | ||
| + | |||
| + | == Solución 3 - Socket login == | ||
| + | |||
| + | '''ServidorUDPLogin:''' | ||
| + | |||
| + | <syntaxhighlight lang="java" line enclose="div" highlight="" > | ||
| + | import java.net.DatagramPacket; | ||
| + | import java.net.DatagramSocket; | ||
| + | import java.net.InetAddress; | ||
| + | |||
| + | public class ServidorUDPLogin { | ||
| + | |||
| + | public static void main(String[] argv) throws Exception { | ||
| + | //Valores con qué comparar | ||
| + | String login = "alumnoUcha"; | ||
| + | String password = "PSP"; | ||
| + | |||
| + | byte[] bufer = new byte[1024];//bufer para recibir el datagrama | ||
| + | //Asocio o socket ó porto 11111 | ||
| + | DatagramSocket socket = new DatagramSocket(11111); | ||
| + | |||
| + | //Agardando datagrama (usuario) | ||
| + | System.out.println("Agardando Datagrama ... "); | ||
| + | DatagramPacket reciboU = new DatagramPacket(bufer, bufer.length); | ||
| + | socket.receive(reciboU);//recibo datagrama | ||
| + | //String user= new String(reciboU.getData());//obteño String | ||
| + | //Se o fago do xeito anterior leeme os bytes enriba do que xa hai; por eso sustituo | ||
| + | String user = new String(reciboU.getData(), 0, reciboU.getLength()); | ||
| + | //Visualizo o que recibo | ||
| + | System.out.println("Nome de usuario: " + user.trim()); | ||
| + | user = user.trim(); //Quitolle os espazos iniciais e finais que puidera ter | ||
| + | if (user.equals(login)) { | ||
| + | System.out.println("Nome de usuario correcto"); | ||
| + | } else { | ||
| + | System.out.println("Nome de usuario incorrecto"); | ||
| + | } | ||
| + | |||
| + | //Agardando datagrama (contrasinal) | ||
| + | System.out.println("Agardando Datagrama ... "); | ||
| + | DatagramPacket reciboP = new DatagramPacket(bufer, bufer.length); | ||
| + | socket.receive(reciboP);//recibo datagrama | ||
| + | //String pass= new String(reciboP.getData());//obteño String | ||
| + | //Se o fago do xeito anterior leeme os bytes enriba do que xa hai; por eso sustituo | ||
| + | String pass = new String(reciboP.getData(), 0, reciboP.getLength()); | ||
| + | //Visualizo o que recibo | ||
| + | System.out.println("Contrasinal : " + pass.trim()); | ||
| + | pass = pass.trim(); //Quitolle os espazos iniciais e finais que puidera ter | ||
| + | if (pass.equals(password)) { | ||
| + | System.out.println("Contrasinal correcto"); | ||
| + | } else { | ||
| + | System.out.println("Contrasinal incorrecto"); | ||
| + | } | ||
| + | |||
| + | socket.close(); //pecho o socket | ||
| + | } | ||
| + | } | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | '''ClienteUDPLogin:''' | ||
| + | <syntaxhighlight lang="java" line enclose="div" highlight="" > | ||
| + | import java.net.DatagramPacket; | ||
| + | import java.net.DatagramSocket; | ||
| + | import java.net.InetAddress; | ||
| + | import java.io.*; | ||
| + | |||
| + | public class ClienteUDPLogin { | ||
| + | |||
| + | public static void main(String[] args) throws Exception { | ||
| + | InetAddress destino = InetAddress.getLocalHost(); | ||
| + | int porto = 11111; //porto ó que envío o datagrama | ||
| + | byte[] mensaxe = new byte[1024]; | ||
| + | BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); | ||
| + | DatagramSocket socket = new DatagramSocket(34567);//Puerto local | ||
| + | |||
| + | //Introduce usuario por teclado | ||
| + | System.out.print("Introduce usuario: "); | ||
| + | String user = in.readLine(); | ||
| + | mensaxe = user.getBytes(); //codifico String a bytes | ||
| + | |||
| + | //Constrúe o datagrama a enviar | ||
| + | DatagramPacket envioU = new DatagramPacket(mensaxe, mensaxe.length, destino, porto); | ||
| + | //Envio datagrama | ||
| + | socket.send(envioU); | ||
| + | |||
| + | //Introduce contrasinal por teclado | ||
| + | System.out.print("Introduce contrasinal: "); | ||
| + | String pass = in.readLine(); | ||
| + | mensaxe = pass.getBytes(); //codifico String a bytes | ||
| + | |||
| + | //Constrúe o datagrama a enviar | ||
| + | DatagramPacket envioP = new DatagramPacket(mensaxe, mensaxe.length, destino, porto); | ||
| + | //Envío datagrama | ||
| + | socket.send(envioP); | ||
| + | |||
| + | socket.close(); //pecho o socket | ||
| + | } | ||
| + | } | ||
| + | </syntaxhighlight> | ||
| + | |||
| + | '''Cuestión'''. Coa solución proposta: | ||
| + | a) Pensas que para o envío de usuario e contrasinal é boa idea o uso de UDP? Ou sería mellor TCP? Por qué? | ||
| + | Probablemente sería máis convinte o uso de TCP. No envío dun usuario e contrasinal é importate a fiabilidade. | ||
| + | Ademáis, así poderíamos facer uso de cifrado con TLS/SSL | ||
| + | |||
| + | b) nun suposto real, tería sentido comprobar o nome de usuario e contrasinal por separado? | ||
| + | Non, deberían ser comprobados nunha tupla conxunta. Por exemplo: | ||
| + | Pode haber dous usuarios, Pepe e Alba, con contrasinais 111 e 222, respectivamente. | ||
| + | A aplicación tal e como está implmentada validaría que un usuario Pepe entrara co contrasinal de Alba. | ||
Revisión actual del 17:12 14 nov 2021
Sumario
Enunciado 1 - Socket que responde a saúdo
Escribe un programa que responda a saúdos usando sockets datagram:
- O programa escoitará polo socket mensaxes que conteñan a cadea de texto "Ola"
- Cando reciba un responderá o seu emisor con outra mensaxe que conteña a cadea "Qué tal?".
Escribe outro programa adicional (cliente) para probar o funcionamiento deste: teremos un emisor (cliente, o que saluda) e un receptor (servidor, o que contesta).
Solución 1
Servidor:
1 import java.io.*;
2 import java.net.*;
3 public class ServidorSaudo {
4 public static void main(String args[]) throws Exception {
5 //Porto polo que escoita o servidor: 9876
6 DatagramSocket serverSocket = new DatagramSocket(9876);
7 byte[] recibidos = new byte[1024];
8 byte[] enviados = new byte[1024];
9 String cadea;
10
11 while(true) {
12 System.out.println ("Esperando datagrama ... ");
13 //Recibo dagragama
14 recibidos = new byte[1024];
15 DatagramPacket paqRecibido = new DatagramPacket(recibidos, recibidos.length);
16 serverSocket.receive(paqRecibido);
17 cadea = new String(paqRecibido.getData());
18
19 //Enderezo orixe
20 InetAddress IPOrixe = paqRecibido.getAddress();
21 int porto = paqRecibido.getPort();
22 /*System.out.println ("\tOrixe: " + IPOrixe + ":" + porto);*/
23 System.out.println ("\tMensaxe recibida: " + cadea.trim());
24
25 //Cadea a devolver
26 String respuesta = "Qué tal?";
27 enviados = respuesta.getBytes();
28
29 //Envío datagrama ó cliente
30 DatagramPacket paqEnviado = new DatagramPacket(enviados, enviados.length, IPOrixe, porto);
31 serverSocket.send(paqEnviado);
32
33 //Para terminar
34 if(!cadea.trim().equals("Ola")) break;
35 }
36 serverSocket.close() ;
37 System.out.println ("Socket pechado ... ");
38 }
39 }
Cliente:
1 import java.io.*;
2 import java.net.*;
3 public class ClienteSaudo {
4 public static void main(String args[]) throws Exception {
5 //Fluxo para entrada estándar
6 BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
7
8 DatagramSocket clientSocket = new DatagramSocket();//socket cliente
9 byte[] enviados = new byte[1024];
10 byte[] recibidos = new byte[1024];
11
12 // Datos do servidor ó que enviar a mensaxe
13 InetAddress IPServidor = InetAddress.getLocalHost() ;// localhost
14 int porto = 9876; // porto polo que escoita
15
16 String cadea = "Ola";
17 enviados = cadea.getBytes();
18
19 //Enviando datagrama ó servidor
20 System.out.println("Enviando " + enviados.length + " bytes ó servidor.");
21 DatagramPacket envio = new DatagramPacket(enviados, enviados.length, IPServidor, porto);
22 clientSocket.send(envio) ;
23
24 // Recibindo datagrama do servidor
25 DatagramPacket recibo = new DatagramPacket(recibidos, recibidos.length);
26 System.out.println("Esperando datagrama ... ");
27 clientSocket.receive(recibo);
28 //Recibe la resposta
29 String resposta = new String(recibo.getData());
30
31 //Obtendo información do datagrama
32 /*InetAddress IPOrixe = recibo.getAddress();
33 int portoOrixe = recibo.getPort();
34 System.out.println("\tProcedente de: " +IPOrixe + ":" + portoOrixe);*/
35 System.out.println("\tDatos: " + resposta.trim());
36 clientSocket.close();//pechar socket
37 }
38 }
Cuestións. Coa solución proposta: a) Qué acontece cando o cliente envía como saúdo Ola? E cando envía calquera outro texto? Con Ola, o servidor segue a escoita. Con calquera outro texto, o servidor finaliza. b) Qué acontece se primeiro se lanza o cliente e despois o servidor? Non funcionará!
Enunciado 2 - Socket intercambia token
Escribe unha parella de programas (A e B) que usen sockets datagram para intercambiar unha mensaxe chamada token:
- O arrincar o programa A enviará unha mensaxe ó B coa palabra "token".
- Cando o B a reciba, enviará de volta a A unha mensaxe coa palabra recibido e terminará
- Cando A reciba a mensaxe de B terminará tamén
Solución 2
TokenA:
1 import java.io.*;
2 import java.net.*;
3
4 public class TokenA {
5
6 public static void main(String args[]) throws Exception {
7 //Fluxo para entrada estandar
8 BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
9
10 DatagramSocket clientSocket = new DatagramSocket();//socket cliente
11 byte[] enviados = new byte[1024];
12 byte[] recibidos = new byte[1024];
13
14 // Datos do servidor ó que enviar a mensaxe
15 InetAddress IPServidor = InetAddress.getLocalHost();// localhost
16 int porto = 9876; //,porto polo que esoita
17
18 String cadea = "token";
19 enviados = cadea.getBytes();
20
21 //Enviando datagrama ó servidor
22 //System.out.println("Enviando " + enviados.length + " bytes ó servidor.");
23 System.out.println("Enviando a palabara: " + cadea);
24 DatagramPacket envio = new DatagramPacket(enviados, enviados.length, IPServidor, porto);
25 clientSocket.send(envio);
26
27 // Recibindo datagrama do servidor
28 DatagramPacket recibo = new DatagramPacket(recibidos, recibidos.length);
29 System.out.println("Esperando datagrama ... ");
30 clientSocket.receive(recibo);
31 //Recibe a resposta
32 String resposta = new String(recibo.getData());
33
34 //Obtendo información do datagrama
35 /*InetAddress IPOrixe = recibo.getAddress();
36 int portoOrixe = recibo.getPort();
37 System.out.println("\tProcedente de: " + IPOrixe + ":" + portoOrixe);*/
38 System.out.println("\tMensaxe recibida: " + resposta.trim());
39 clientSocket.close();//cerrar socket
40 }
41 }
TokenB:
1 import java.io.*;
2 import java.net.*;
3
4 public class TokenB {
5
6 public static void main(String args[]) throws Exception {
7 //Porto polo que escoita o servidor: 9876
8 DatagramSocket serverSocket = new DatagramSocket(9876);
9 byte[] recibidos = new byte[1024];
10 byte[] enviados = new byte[1024];
11 String cadea;
12
13 System.out.println("Esperando datagrama ... ");
14 //Recibo datagrama
15 DatagramPacket paqRecibido = new DatagramPacket(recibidos, recibidos.length);
16 serverSocket.receive(paqRecibido);
17 cadea = new String(paqRecibido.getData());
18
19 //Enderezo orixe
20 InetAddress IPOrixe = paqRecibido.getAddress();
21 int porto = paqRecibido.getPort();
22 /*System.out.println ("\tOrixe: " + IPOrixe + ":" + porto);*/
23 System.out.println("\tMensaxe recibida: " + cadea.trim());
24
25 //Cadea a devolver
26 String resposta = "Recibido";
27 enviados = resposta.getBytes();
28
29 //Envío datagrama ó cliente
30 DatagramPacket paqEnviado = new DatagramPacket(enviados, enviados.length, IPOrixe, porto);
31 serverSocket.send(paqEnviado);
32 System.out.println("\tMensaxe enviada: " + resposta);
33
34 serverSocket.close();
35 System.out.println("Socket pechado ... ");
36 }
37 }
Cuestión. Coa solución proposta: a) Funciona correctamente se primeiro executamos o tokenA e despois o tokenB? Non, porque o tokenB é o que está inicialmente a escoita e o tokenA o que envía.
Enunciado 3 - Socket login
Crea un programa cliente/servidor UDP:
- O cliente solicita ó usuario un nome de usuario e un contrasinal.
- O servidor recibirá esa información e encargarase de comparala con dous valores de usuario e contrasinal predeterminados (por exemplo, "alumnoUcha" e "PSP"), gardados en dúas variables.
- O servidor informará pola súa consola da coincidencia ou non coincidencia dos datos introducidos polo usuario cos mantidos nesas dúas variables
Pensas que para o envío de usuario e contrasinal é boa idea o uso de UDP? Ou sería mellor TCP? Por qué?
Solución 3 - Socket login
ServidorUDPLogin:
1 import java.net.DatagramPacket;
2 import java.net.DatagramSocket;
3 import java.net.InetAddress;
4
5 public class ServidorUDPLogin {
6
7 public static void main(String[] argv) throws Exception {
8 //Valores con qué comparar
9 String login = "alumnoUcha";
10 String password = "PSP";
11
12 byte[] bufer = new byte[1024];//bufer para recibir el datagrama
13 //Asocio o socket ó porto 11111
14 DatagramSocket socket = new DatagramSocket(11111);
15
16 //Agardando datagrama (usuario)
17 System.out.println("Agardando Datagrama ... ");
18 DatagramPacket reciboU = new DatagramPacket(bufer, bufer.length);
19 socket.receive(reciboU);//recibo datagrama
20 //String user= new String(reciboU.getData());//obteño String
21 //Se o fago do xeito anterior leeme os bytes enriba do que xa hai; por eso sustituo
22 String user = new String(reciboU.getData(), 0, reciboU.getLength());
23 //Visualizo o que recibo
24 System.out.println("Nome de usuario: " + user.trim());
25 user = user.trim(); //Quitolle os espazos iniciais e finais que puidera ter
26 if (user.equals(login)) {
27 System.out.println("Nome de usuario correcto");
28 } else {
29 System.out.println("Nome de usuario incorrecto");
30 }
31
32 //Agardando datagrama (contrasinal)
33 System.out.println("Agardando Datagrama ... ");
34 DatagramPacket reciboP = new DatagramPacket(bufer, bufer.length);
35 socket.receive(reciboP);//recibo datagrama
36 //String pass= new String(reciboP.getData());//obteño String
37 //Se o fago do xeito anterior leeme os bytes enriba do que xa hai; por eso sustituo
38 String pass = new String(reciboP.getData(), 0, reciboP.getLength());
39 //Visualizo o que recibo
40 System.out.println("Contrasinal : " + pass.trim());
41 pass = pass.trim(); //Quitolle os espazos iniciais e finais que puidera ter
42 if (pass.equals(password)) {
43 System.out.println("Contrasinal correcto");
44 } else {
45 System.out.println("Contrasinal incorrecto");
46 }
47
48 socket.close(); //pecho o socket
49 }
50 }
ClienteUDPLogin:
1 import java.net.DatagramPacket;
2 import java.net.DatagramSocket;
3 import java.net.InetAddress;
4 import java.io.*;
5
6 public class ClienteUDPLogin {
7
8 public static void main(String[] args) throws Exception {
9 InetAddress destino = InetAddress.getLocalHost();
10 int porto = 11111; //porto ó que envío o datagrama
11 byte[] mensaxe = new byte[1024];
12 BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
13 DatagramSocket socket = new DatagramSocket(34567);//Puerto local
14
15 //Introduce usuario por teclado
16 System.out.print("Introduce usuario: ");
17 String user = in.readLine();
18 mensaxe = user.getBytes(); //codifico String a bytes
19
20 //Constrúe o datagrama a enviar
21 DatagramPacket envioU = new DatagramPacket(mensaxe, mensaxe.length, destino, porto);
22 //Envio datagrama
23 socket.send(envioU);
24
25 //Introduce contrasinal por teclado
26 System.out.print("Introduce contrasinal: ");
27 String pass = in.readLine();
28 mensaxe = pass.getBytes(); //codifico String a bytes
29
30 //Constrúe o datagrama a enviar
31 DatagramPacket envioP = new DatagramPacket(mensaxe, mensaxe.length, destino, porto);
32 //Envío datagrama
33 socket.send(envioP);
34
35 socket.close(); //pecho o socket
36 }
37 }
Cuestión. Coa solución proposta: a) Pensas que para o envío de usuario e contrasinal é boa idea o uso de UDP? Ou sería mellor TCP? Por qué? Probablemente sería máis convinte o uso de TCP. No envío dun usuario e contrasinal é importate a fiabilidade. Ademáis, así poderíamos facer uso de cifrado con TLS/SSL
b) nun suposto real, tería sentido comprobar o nome de usuario e contrasinal por separado? Non, deberían ser comprobados nunha tupla conxunta. Por exemplo: Pode haber dous usuarios, Pepe e Alba, con contrasinais 111 e 222, respectivamente. A aplicación tal e como está implmentada validaría que un usuario Pepe entrara co contrasinal de Alba.