práctica 3, falta la última parte

This commit is contained in:
2026-03-04 20:27:45 +01:00
commit aa8b7b30fb
21 changed files with 2705 additions and 0 deletions

View File

@@ -0,0 +1,347 @@
package es.um.redes.nanoFiles.udp.client;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.SocketTimeoutException;
import java.util.Map;
import java.util.LinkedHashMap;
import es.um.redes.nanoFiles.tcp.client.NFConnector;
import es.um.redes.nanoFiles.application.NanoFiles;
import es.um.redes.nanoFiles.udp.message.DirMessage;
import es.um.redes.nanoFiles.udp.message.DirMessageOps;
import es.um.redes.nanoFiles.util.FileInfo;
/**
* Cliente con métodos de consulta y actualización específicos del directorio
*/
public class DirectoryConnector {
/**
* Puerto en el que atienden los servidores de directorio
*/
private static final int DIRECTORY_PORT = 6868;
/**
* Tiempo máximo en milisegundos que se esperará a recibir una respuesta por el
* socket antes de que se deba lanzar una excepción SocketTimeoutException para
* recuperar el control
*/
private static final int TIMEOUT = 1000;
/**
* Número de intentos máximos para obtener del directorio una respuesta a una
* solicitud enviada. Cada vez que expira el timeout sin recibir respuesta se
* cuenta como un intento.
*/
private static final int MAX_NUMBER_OF_ATTEMPTS = 5;
/**
* Socket UDP usado para la comunicación con el directorio
*/
private DatagramSocket socket;
/**
* Dirección de socket del directorio (IP:puertoUDP)
*/
private InetSocketAddress directoryAddress;
/**
* Nombre/IP del host donde se ejecuta el directorio
*/
private String directoryHostname;
public static class DownloadedFile {
public final String filename;
public final long filesize;
public final byte[] data;
public final String filehash;
public DownloadedFile(String filename, long fsize, byte[] data, String filehash) {
this.filename = filename;
this.filesize = fsize;
this.data = data;
this.filehash = filehash;
}
}
public DirectoryConnector(String hostname) throws IOException {
// Guardamos el string con el nombre/IP del host
directoryHostname = hostname;
/*
* DONE: (Boletín SocketsUDP) Convertir el string 'hostname' a InetAddress y
* guardar la dirección de socket (address:DIRECTORY_PORT) del directorio en el
* atributo directoryAddress, para poder enviar datagramas a dicho destino.
*/
/*
* DONE: (Boletín SocketsUDP) Crea el socket UDP en cualquier puerto para enviar
* datagramas al directorio
*/
directoryAddress = new InetSocketAddress(InetAddress.getByName(hostname), DIRECTORY_PORT);
socket = new DatagramSocket(6767);
}
/**
* Método para enviar y recibir datagramas al/del directorio
*
* @param requestData los datos a enviar al directorio (mensaje de solicitud)
* @return los datos recibidos del directorio (mensaje de respuesta)
*/
private byte[] sendAndReceiveDatagrams(byte[] requestData) {
byte responseData[] = new byte[DirMessage.PACKET_MAX_SIZE];
byte response[] = null;
if (directoryAddress == null) {
System.err.println("DirectoryConnector.sendAndReceiveDatagrams: UDP server destination address is null!");
System.err.println(
"DirectoryConnector.sendAndReceiveDatagrams: make sure constructor initializes field \"directoryAddress\"");
System.exit(-1);
}
if (socket == null) {
System.err.println("DirectoryConnector.sendAndReceiveDatagrams: UDP socket is null!");
System.err.println(
"DirectoryConnector.sendAndReceiveDatagrams: make sure constructor initializes field \"socket\"");
System.exit(-1);
}
/*
* DONE¿?: (Boletín SocketsUDP) Enviar datos en un datagrama al directorio y
* recibir una respuesta. El array devuelto debe contener únicamente los datos
* recibidos, *NO* el búfer de recepción al completo.
*/
DatagramPacket pktToServer = new DatagramPacket(requestData, requestData.length, directoryAddress);
DatagramPacket pktFromServer = new DatagramPacket(responseData, responseData.length);
int intentos = 0;
boolean recibido = false;
while (intentos < MAX_NUMBER_OF_ATTEMPTS && !recibido) {
try {
socket.send(pktToServer);
socket.setSoTimeout(TIMEOUT);
socket.receive(pktFromServer);
recibido = true;
} catch (IOException e) {
intentos++;
if (intentos == MAX_NUMBER_OF_ATTEMPTS) {
System.err.println("DirectoryConnector.sendAndReceiveDatagrams: socket.receive()");
System.exit(-1);
}
}
}
String servResp = new String(responseData, 0, pktFromServer.getLength());
response = servResp.getBytes();
System.out.println("Hemos recibido " + servResp);
/*
* done: (Boletín SocketsUDP) Una vez el envío y recepción asumiendo un canal
* confiable (sin pérdidas) esté terminado y probado, debe implementarse un
* mecanismo de retransmisión usando temporizador, en caso de que no se reciba
* respuesta en el plazo de TIMEOUT. En caso de salte el timeout, se debe volver
* a enviar el datagrama y tratar de recibir respuestas, reintentando como
* máximo en MAX_NUMBER_OF_ATTEMPTS ocasiones.
*/
/*
* DONE: (Boletín SocketsUDP) Las excepciones que puedan lanzarse al
* leer/escribir en el socket deben ser capturadas y tratadas en este método. Si
* se produce una excepción de entrada/salida (error del que no es posible
* recuperarse), se debe informar y terminar el programa.
*/
/*
* NOTA: Las excepciones deben tratarse de la más concreta a la más genérica.
* SocketTimeoutException es más concreta que IOException.
*/
if (response != null && response.length == responseData.length) {
System.err.println("Your response is as large as the datagram reception buffer!!\n"
+ "You must extract from the buffer only the bytes that belong to the datagram!");
}
return response;
}
/**
* Método para probar la comunicación con el directorio mediante el envío y
* recepción de mensajes sin formatear ("en crudo")
*
* @return verdadero si se ha enviado un datagrama y recibido una respuesta
*/
public boolean testSendAndReceive() {
/*
* DONE: (Boletín SocketsUDP) Probar el correcto funcionamiento de
* sendAndReceiveDatagrams. Se debe enviar un datagrama con la cadena "ping" y
* comprobar que la respuesta recibida empieza por "pingok". En tal caso,
* devuelve verdadero, falso si la respuesta no contiene los datos esperados.
*/
boolean success = false;
byte[] reqData = new String("ping").getBytes();
byte[] resp = sendAndReceiveDatagrams(reqData);
if (resp != null) {
String respStr = new String(resp, 0 , resp.length);
if (respStr.startsWith("pingok")) {
success = true;
}
}
return success;
}
public String getDirectoryHostname() {
return directoryHostname;
}
/**
* Método para "hacer ping" al directorio, comprobar que está operativo y que
* usa un protocolo compatible. Este método no usa mensajes bien formados.
*
* @return Verdadero si
*/
public boolean pingDirectoryRaw() {
boolean success = false;
byte[] reqData = new String("ping&" + NanoFiles.PROTOCOL_ID).getBytes();
byte[] resp = sendAndReceiveDatagrams(reqData);
if (resp != null) {
String recv = new String(resp, 0, resp.length);
if (recv.equals("welcome")) {
success = true;
}
}
/*
* done: (Boletín EstructuraNanoFiles) Basándose en el código de
* "testSendAndReceive", contactar con el directorio, enviándole nuestro
* PROTOCOL_ID (ver clase NanoFiles). Se deben usar mensajes "en crudo" (sin un
* formato bien definido) para la comunicación.
*
* PASOS: 1.Crear el mensaje a enviar (String "ping&protocolId"). 2.Crear un
* datagrama con los bytes en que se codifica la cadena : 4.Enviar datagrama y
* recibir una respuesta (sendAndReceiveDatagrams). : 5. Comprobar si la cadena
* recibida en el datagrama de respuesta es "welcome", imprimir si éxito o
* fracaso. 6.Devolver éxito/fracaso de la operación.
*/
return success;
}
/**
* Método para "hacer ping" al directorio, comprobar que está operativo y que es
* compatible.
*
* @return Verdadero si el directorio está operativo y es compatible
*/
public boolean pingDirectory() {
boolean success = false;
/*
* done: (Boletín MensajesASCII) Hacer ping al directorio 1.Crear el mensaje a
* enviar (objeto DirMessage) con atributos adecuados (operation, etc.) NOTA:
* Usar como operaciones las constantes definidas en la clase DirMessageOps :
* 2.Convertir el objeto DirMessage a enviar a un string (método toString)
* 3.Crear un datagrama con los bytes en que se codifica la cadena : 4.Enviar
* datagrama y recibir una respuesta (sendAndReceiveDatagrams). : 5.Convertir
* respuesta recibida en un objeto DirMessage (método DirMessage.fromString)
* 6.Extraer datos del objeto DirMessage y procesarlos 7.Devolver éxito/fracaso
* de la operación
*/
DirMessage ping = new DirMessage(DirMessageOps.OPERATION_PING);
String pingStr = ping.toString();
byte[] pingBytes = pingStr.getBytes();
byte[] resp = sendAndReceiveDatagrams(pingBytes);
String respStr = new String(resp, 0, resp.length);
DirMessage respPing = DirMessage.fromString(respStr);
success = (respPing.getOperation().equals(DirMessageOps.OPERATION_PING_OK));
return success;
}
/**
* Método para dar de alta como servidor de ficheros en el puerto indicado.
*
* @param serverPort El puerto TCP en el que este peer sirve ficheros a otros
* @return Verdadero si el directorio tiene registrado a este peer como servidor
* y acepta la lista de ficheros, falso en caso contrario.
*/
public boolean registerFileServer(int serverPort) {
boolean success = false;
// TODO: Ver TODOs en pingDirectory y seguir esquema similar
return success;
}
/**
* Método para obtener la lista de ficheros alojados en el directorio. Para cada
* fichero se debe obtener un objeto FileInfo con nombre, tamaño y hash.
*
* @return Los ficheros disponibles en el directorio, o null si el directorio no
* pudo satisfacer nuestra solicitud
*/
public FileInfo[] getFileList() {
FileInfo[] filelist = new FileInfo[0];
// TODO: Ver TODOs en pingDirectory y seguir esquema similar
return filelist;
}
public Map<String, InetSocketAddress> getPeerList() {
Map<String, InetSocketAddress> peers = new LinkedHashMap<String, InetSocketAddress>();
return peers;
}
public Map<String, InetSocketAddress[]> searchFilesByHash(String hashSubstring) {
Map<String, InetSocketAddress[]> results = new LinkedHashMap<String, InetSocketAddress[]>();
return results;
}
public DownloadedFile downloadFileFromDirectory(String hashSubstring) {
byte[] fileData = null;
String filename = null;
long filesize = -1;
String filehash = null;
return new DownloadedFile(filename, filesize, fileData, filehash);
}
/**
* Método para darse de baja como servidor de ficheros.
*
* @return Verdadero si el directorio tiene registrado a este peer como servidor
* y ha dado de baja sus ficheros.
*/
public boolean unregisterFileServer() {
boolean success = false;
return success;
}
}

View File

@@ -0,0 +1,160 @@
package es.um.redes.nanoFiles.udp.message;
import es.um.redes.nanoFiles.application.NanoFiles;
/**
* Clase que modela los mensajes del protocolo de comunicación entre pares para
* implementar el explorador de ficheros remoto (servidor de ficheros). Estos
* mensajes son intercambiados entre las clases DirectoryServer y
* DirectoryConnector, y se codifican como texto en formato "campo:valor".
*
* @author rtitos
*
*/
public class DirMessage {
public static final int PACKET_MAX_SIZE = 65507; // 65535 - 8 (UDP header) - 20 (IP header)
private static final char DELIMITER = ':'; // Define el delimitador
private static final char END_LINE = '\n'; // Define el carácter de fin de línea
/**
* Nombre del campo que define el tipo de mensaje (primera línea)
*/
private static final String FIELDNAME_OPERATION = "operation";
/*
* TODO: (Boletín MensajesASCII) Definir de manera simbólica los nombres de
* todos los campos que pueden aparecer en los mensajes de este protocolo
* (formato campo:valor)
*/
private static final String FIELDNAME_PROTOCOL = "protocol";
/**
* Tipo del mensaje, de entre los tipos definidos en PeerMessageOps.
*/
private String operation = DirMessageOps.OPERATION_INVALID;
/**
* Identificador de protocolo usado, para comprobar compatibilidad del directorio.
*/
private String protocolId;
/*
* TODO: (Boletín MensajesASCII) Crear un atributo correspondiente a cada uno de
* los campos de los diferentes mensajes de este protocolo.
*/
public DirMessage(String op) {
operation = op;
}
/*
* TODO: (Boletín MensajesASCII) Crear diferentes constructores adecuados para
* construir mensajes de diferentes tipos con sus correspondientes argumentos
* (campos del mensaje)
*/
public String getOperation() {
return operation;
}
/*
* TODO: (Boletín MensajesASCII) Crear métodos getter y setter para obtener los
* valores de los atributos de un mensaje. Se aconseja incluir código que
* compruebe que no se modifica/obtiene el valor de un campo (atributo) que no
* esté definido para el tipo de mensaje dado por "operation".
*/
public void setProtocolID(String protocolIdent) {
if (!operation.equals(DirMessageOps.OPERATION_PING)) {
throw new RuntimeException(
"DirMessage: setProtocolId called for message of unexpected type (" + operation + ")");
}
protocolId = protocolIdent;
}
public String getProtocolId() {
return protocolId;
}
/**
* Método que convierte un mensaje codificado como una cadena de caracteres, a
* un objeto de la clase PeerMessage, en el cual los atributos correspondientes
* han sido establecidos con el valor de los campos del mensaje.
*
* @param message El mensaje recibido por el socket, como cadena de caracteres
* @return Un objeto PeerMessage que modela el mensaje recibido (tipo, valores,
* etc.)
*/
public static DirMessage fromString(String message) {
/*
* TODO: (Boletín MensajesASCII) Usar un bucle para parsear el mensaje línea a
* línea, extrayendo para cada línea el nombre del campo y el valor, usando el
* delimitador DELIMITER, y guardarlo en variables locales.
*/
// System.out.println("DirMessage read from socket:");
// System.out.println(message);
String[] lines = message.split(END_LINE + "");
// Local variables to save data during parsing
DirMessage m = null;
for (String line : lines) {
int idx = line.indexOf(DELIMITER); // Posición del delimitador
String fieldName = line.substring(0, idx).toLowerCase(); // minúsculas
String value = line.substring(idx + 1).trim();
switch (fieldName) {
case FIELDNAME_OPERATION: {
assert (m == null);
m = new DirMessage(value);
break;
}
case FIELDNAME_PROTOCOL: {
m.setProtocolID(value);
break;
}
default:
System.err.println("PANIC: DirMessage.fromString - message with unknown field name " + fieldName);
System.err.println("Message was:\n" + message);
System.exit(-1);
}
}
return m;
}
/**
* Método que devuelve una cadena de caracteres con la codificación del mensaje
* según el formato campo:valor, a partir del tipo y los valores almacenados en
* los atributos.
*
* @return La cadena de caracteres con el mensaje a enviar por el socket.
*/
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(FIELDNAME_OPERATION + DELIMITER + operation + END_LINE); // Construimos el campo
/*
* TODO: (Boletín MensajesASCII) En función de la operación del mensaje, crear
* una cadena la operación y concatenar el resto de campos necesarios usando los
* valores de los atributos del objeto.
*/
switch (operation) {
case DirMessageOps.OPERATION_PING:
sb.append(FIELDNAME_PROTOCOL + DELIMITER + NanoFiles.PROTOCOL_ID + END_LINE);
break;
default:
break;
}
sb.append(END_LINE); // Marcamos el final del mensaje
return sb.toString();
}
}

View File

@@ -0,0 +1,22 @@
package es.um.redes.nanoFiles.udp.message;
public class DirMessageOps {
/*
* TODO: (Boletín MensajesASCII) Añadir aquí todas las constantes que definen
* los diferentes tipos de mensajes del protocolo de comunicación con el
* directorio (valores posibles del campo "operation").
*/
public static final String OPERATION_INVALID = "invalid_operation";
public static final String OPERATION_PING = "ping";
public static final String OPERATION_PING_OK = "pingOk";
public static final String OPERATION_PING_BAD = "pingBad";
// TODO: definir las operaciones del protocolo de directorio
}

View File

@@ -0,0 +1,264 @@
package es.um.redes.nanoFiles.udp.server;
import java.io.File;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetSocketAddress;
import java.net.SocketException;
import java.util.Arrays;
import java.util.LinkedHashMap;
import es.um.redes.nanoFiles.application.NanoFiles;
import es.um.redes.nanoFiles.udp.message.DirMessage;
import es.um.redes.nanoFiles.udp.message.DirMessageOps;
import es.um.redes.nanoFiles.util.FileInfo;
import es.um.redes.nanoFiles.util.NickGenerator;
public class NFDirectoryServer {
/**
* Número de puerto UDP en el que escucha el directorio
*/
public static final int DIRECTORY_PORT = 6868;
/**
* Socket de comunicación UDP con el cliente UDP (DirectoryConnector)
*/
private DatagramSocket socket = null;
/*
* TODO: Añadir aquí como atributos las estructuras de datos que sean necesarias
* para mantener en el directorio cualquier información necesaria para la
* funcionalidad del sistema nanoFilesP2P: ficheros alojados, servidores
* registrados, etc.
*/
/**
* Lista de ficheros alojados en el directorio.
*/
private FileInfo[] directoryFiles;
/**
* Lista de servidores registrados (IP, puerto TCP).
*/
private LinkedHashMap<String, InetSocketAddress> registeredPeers;
/**
* Probabilidad de descartar un mensaje recibido en el directorio (para simular
* enlace no confiable y testear el código de retransmisión)
*/
private double messageDiscardProbability;
public NFDirectoryServer(double corruptionProbability, String directoryFilesPath) throws SocketException {
/*
* Guardar la probabilidad de pérdida de datagramas (simular enlace no
* confiable)
*/
messageDiscardProbability = corruptionProbability;
/*
* Cargar los ficheros del directorio compartido.
*/
File dir = new File(directoryFilesPath);
if (!dir.exists()) {
dir.mkdirs();
}
directoryFiles = FileInfo.loadFilesFromFolder(directoryFilesPath);
System.out.println("* Directory loaded " + directoryFiles.length + " files from " + directoryFilesPath);
/*
* DONE: (Boletín SocketsUDP) Inicializar el atributo socket: Crear un socket
* UDP ligado al puerto especificado por el argumento directoryPort en la
* máquina local,
*/
socket = new DatagramSocket(DIRECTORY_PORT);
/*
* DONE: (Boletín SocketsUDP) Inicializar atributos que mantienen el estado del
* servidor de directorio: peers registrados, etc.)
*/
registeredPeers = new LinkedHashMap<String, InetSocketAddress>();
if (NanoFiles.testModeUDP) {
if (socket == null) {
System.err.println("[testMode] NFDirectoryServer: code not yet fully functional.\n"
+ "Check that all TODOs in its constructor and 'run' methods have been correctly addressed!");
System.exit(-1);
}
}
}
public DatagramPacket receiveDatagram() throws IOException {
DatagramPacket datagramReceivedFromClient = null;
boolean datagramReceived = false;
while (!datagramReceived) {
/*
* DONE?: (Boletín SocketsUDP) Crear un búfer para recibir datagramas y un
* datagrama asociado al búfer (datagramReceivedFromClient)
*/
/*
* DONE: (Boletín SocketsUDP) Recibimos a través del socket un datagrama
*/
byte[] recvBuf = new byte[DirMessage.PACKET_MAX_SIZE];
datagramReceivedFromClient = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(datagramReceivedFromClient);
// Vemos si el mensaje debe ser ignorado (simulación de un canal no confiable)
double rand = Math.random();
if (rand < messageDiscardProbability) {
System.err.println("Directory ignored datagram from " + datagramReceivedFromClient.getSocketAddress());
} else {
datagramReceived = true;
}
}
return datagramReceivedFromClient;
}
public void runTest() throws IOException {
System.out.println("[testMode] Directory starting...");
System.out.println("[testMode] Attempting to receive 'ping' message...");
DatagramPacket rcvDatagram = receiveDatagram();
sendResponseTestMode(rcvDatagram);
System.out.println("[testMode] Attempting to receive 'ping&PROTOCOL_ID' message...");
rcvDatagram = receiveDatagram();
sendResponseTestMode(rcvDatagram);
}
private void sendResponseTestMode(DatagramPacket pkt) throws IOException {
/*
* DONE?: (Boletín SocketsUDP) Construir un String partir de los datos recibidos
* en el datagrama pkt. A continuación, imprimir por pantalla dicha cadena a
* modo de depuración.
*/
/*
* DONE: (Boletín SocketsUDP) Después, usar la cadena para comprobar que su
* valor es "ping"; en ese caso, enviar como respuesta un datagrama con la
* cadena "pingok". Si el mensaje recibido no es "ping", se informa del error y
* se envía "invalid" como respuesta.
*/
/*
* TODO: (Boletín Estructura-NanoFiles) Ampliar el código para que, en el caso
* de que la cadena recibida no sea exactamente "ping", comprobar si comienza
* por "ping&" (es del tipo "ping&PROTOCOL_ID", donde PROTOCOL_ID será el
* identificador del protocolo diseñado por el grupo de prácticas (ver
* NanoFiles.PROTOCOL_ID). Se debe extraer el "protocol_id" de la cadena
* recibida y comprobar que su valor coincide con el de NanoFiles.PROTOCOL_ID,
* en cuyo caso se responderá con "welcome" (en otro caso, "denied").
*/
String messageFromClient = new String(pkt.getData(), 0, pkt.getLength());
String send;
if (messageFromClient.equals("ping")) {
send = "pingok";
} else {
if (messageFromClient.startsWith("ping&")) {
String protocol = messageFromClient.substring(5);
if (protocol.equals(NanoFiles.PROTOCOL_ID)) {
send = "welcome";
} else {
send = "denied";
}
} else {
send = "invalid";
}
}
InetSocketAddress sender = (InetSocketAddress) pkt.getSocketAddress();
byte[] sendData = send.getBytes();
DatagramPacket resp = new DatagramPacket(sendData, sendData.length, sender);
socket.send(resp);
}
public void run() throws IOException {
System.out.println("Directory starting...");
while (true) { // Bucle principal del servidor de directorio
DatagramPacket rcvDatagram = receiveDatagram();
sendResponse(rcvDatagram);
}
}
private void sendResponse(DatagramPacket pkt) throws IOException {
/*
* TODO: (Boletín MensajesASCII) Construir String partir de los datos recibidos
* en el datagrama pkt. A continuación, imprimir por pantalla dicha cadena a
* modo de depuración. Después, usar la cadena para construir un objeto
* DirMessage que contenga en sus atributos los valores del mensaje. A partir de
* este objeto, se podrá obtener los valores de los campos del mensaje mediante
* métodos "getter" para procesar el mensaje y consultar/modificar el estado del
* servidor.
*/
String receivedData = new String(pkt.getData(), 0, pkt.getLength());
System.out.println("Hemos recibido: \n" + receivedData);
DirMessage receivedMsg = DirMessage.fromString(receivedData);
/*
* TODO: Una vez construido un objeto DirMessage con el contenido del datagrama
* recibido, obtener el tipo de operación solicitada por el mensaje y actuar en
* consecuencia, enviando uno u otro tipo de mensaje en respuesta.
*/
String operation = DirMessageOps.OPERATION_INVALID; // TODO: Cambiar!
if (receivedMsg != null) {
operation = receivedMsg.getOperation();
}
/*
* TODO: (Boletín MensajesASCII) Construir un objeto DirMessage (msgToSend) con
* la respuesta a enviar al cliente, en función del tipo de mensaje recibido,
* leyendo/modificando según sea necesario el "estado" guardado en el servidor
* de directorio (atributos files, etc.). Los atributos del objeto DirMessage
* contendrán los valores adecuados para los diferentes campos del mensaje a
* enviar como respuesta (operation, etc.)
*/
switch (operation) {
case DirMessageOps.OPERATION_PING: {
/*
* done: (Boletín MensajesASCII) Comprobamos si el protocolId del mensaje del
* cliente coincide con el nuestro.
*/
String protocolId = receivedMsg.getProtocolId();
System.out.println(protocolId.equals(NanoFiles.PROTOCOL_ID));
if (protocolId.equals(NanoFiles.PROTOCOL_ID)) {
operation = DirMessageOps.OPERATION_PING_OK;
} else {
operation = DirMessageOps.OPERATION_PING_BAD;
}
/*
* done: (Boletín MensajesASCII) Construimos un mensaje de respuesta que indique
* el éxito/fracaso del ping (compatible, incompatible), y lo devolvemos como
* resultado del método.
*/
/*
* TODO: (Boletín MensajesASCII) Imprimimos por pantalla el resultado de
* procesar la petición recibida (éxito o fracaso) con los datos relevantes, a
* modo de depuración en el servidor
*/
break;
}
default:
System.err.println("Unexpected message operation: \"" + operation + "\"");
System.exit(-1);
}
/*
* TODO: (Boletín MensajesASCII) Convertir a String el objeto DirMessage
* (msgToSend) con el mensaje de respuesta a enviar, extraer los bytes en que se
* codifica el string y finalmente enviarlos en un datagrama
*/
DirMessage msgToSend = new DirMessage(operation);
String msgToSendStr = msgToSend.toString();
byte[] dataToSend = msgToSendStr.getBytes();
InetSocketAddress clientAddr = (InetSocketAddress) pkt.getSocketAddress();
DatagramPacket pktToClient = new DatagramPacket(dataToSend, dataToSend.length, clientAddr);
socket.send(pktToClient);
}
}