Solucións as prácticas con Sockets UDP

De MediaWiki
Ir a la navegación Ir a la búsqueda

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) 

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.