Hola Lorenzo!
Al igual que hice en el otro hilo repito lo mismo, se trata de una aportación valiosa porque se practica con muchos conceptos interesantes. Con tu permiso voy a trasladar el código que has creado para que esté visible dentro del hilo del foro y las personas que lo vean puedan hacerse una idea sobre el código sin tener que descargar el fichero como adjunto.
Clase ServidorDeFicheros
import java.io.*;
import java.net.*;
public class ServidorDeFicheros
{
public static final int PORT = 4444;
public static void main (String args[]) {
int identificador = 1;
ServerSocket servidor = null;
Socket cliente = null;
try{ servidor = new ServerSocket(PORT);
}catch(IOException e){System.out.println("Error al conectar con el servidor"); System.exit(-1);}
/* Se bloquea mientras escucha */
System.out.println("Servidor escuchando: " + servidor + " " + servidor.getInetAddress());
while(true){
try { cliente = servidor.accept(); } catch (IOException e){ System.out.println("Error al conectar con cliente " + identificador); }
new HiloPeticionCliente(cliente, identificador).start();
identificador++;
}
}
}
Clase HiloPeticionCliente
import java.io.*;
import java.net.*;
import java.nio.channels.FileChannel; import java.nio.channels.FileLock; import java.nio.channels.OverlappingFileLockException; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Paths; import java.nio.file.StandardOpenOption;
public class HiloPeticionCliente extends Thread {
Socket cliente;
int identificador;
BufferedReader entrada = null;
//PrintWriter salida = null;
OutputStream sendChannel = null;
String cadena = ""; String comando = ""; String orden = ""; //Strings para recibir y gestionar la orden del usuario.
boolean primerEspacio = false;
//Variables para la gestión del bloqueo de archivo seleccionado
boolean bloqueado = false;
FileChannel channel; FileLock lock; File archivoBloqueado;
RandomAccessFile accesoABloqueo;
public HiloPeticionCliente (Socket cliente, int identificador){
this.cliente = cliente; this.identificador = identificador; }
public void run(){
while(!cliente.isClosed()){
leerOrdenCliente();
System.out.println("Buscando archivo solicitado en comando: " + cadena);
procesarOrdenCliente();
switch(orden){ //coge la orden y la compara con las aceptadas por la máquina, el resto indica que no son correctas en el default mandando -1
case "bye": System.out.println("Finalizada la conexion con el cliente " + identificador);
try{ cliente.close();} catch(IOException e){}; interrupt(); break;
case "get": getArchivo(); break;
case "lock": lockArchivo(); break;
case "put": putArchivoModificado(); break;
case "unlock": unlockArchivo(); break;
default: try { sendChannel.write(-1); } catch (Exception e){} comando = ""; orden = "";
}
}
}
/*lee la entrada del Cliente y devuelve String */
private String leerOrdenCliente() { try{
//Establece canal de entrada
entrada = new BufferedReader (new InputStreamReader(cliente.getInputStream()));
//Establece canal envio archivos
sendChannel = cliente.getOutputStream();
//lectura entrada usuario
cadena = entrada.readLine();
} catch(IOException e ) { System.out.println(e.getMessage()); }
return cadena;
}
/*Traduce la entrada del cliente dividiendo la orden del fichero a tratar*/
private void procesarOrdenCliente() { //comprueba si el comando introducido es mayor a 3 letras (get, put, bye) y si es así guarda hasta el primer espacio
if(cadena.length() > 3){
for (int x = 0; x < cadena.length(); x++){
//guarda la orden hasta el espacio, get lock o unlock en el String orden
if(cadena.substring(x, x+1).equals(" ") && !primerEspacio){ orden = cadena.substring(0, x); primerEspacio = true; }
// elimina espacios y comillas de la orden recibida y los guarda en comando
if(!cadena.substring(x, x+1).equals(" ") && !cadena.substring(x, x+1).equals("\"")){ comando = comando + cadena.substring(x, x+1); }//final for
}
primerEspacio = false; //al salir del bucle for , iniciamos el boolean primer espacio a false para la proxima entrada.
} else orden = cadena; }
/*Busca el archivo de la orden get */
private void getArchivo(){ //crea instancia de clase buscar archivo y invoca a la funcion buscador para encontrar el archivo solicitado
if(!bloqueado){ //si no está bloqueado significa que es un get archivo normal
if(comando.length() > 3){ //comando debe contener get y además el archivo a buscar, más de 3 caracteres.
File archivoEncontrado = buscarArchivo();
if(archivoEncontrado != null){
new HiloEnvio (cliente, archivoEncontrado).start(); } else { try { sendChannel.write(-1); } catch (Exception e){} }
comando = ""; orden = ""; } else try { sendChannel.write(-1); } catch (Exception e){}
}else {
try{
Path archivoModificado = Paths.get("C:/Mantequilla.txt");
try{
desbloquearCanal(); //desbloqueo del archivo bloqueado
byte[] contenedor = Files.readAllBytes(archivoBloqueado.toPath());
Files.write(archivoModificado, contenedor, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
try{ sleep(1000); }catch (InterruptedException e) { e.printStackTrace(); }
lock = channel.lock();
}catch (IOException e){ }
}catch(Exception e){};
cambioRealizado(); }
}
/*Put sobreescribir archivo con archivo modificado*/
private void putArchivoModificado(){
if (bloqueado){
Path archivoModificado = Paths.get("C:/Mantequilla.txt");
try{
desbloquearCanal(); //desbloqueo del archivo bloqueado
byte[] arrayBytes = Files.readAllBytes(archivoModificado); //pasamos el contenido del archivo modificado a un array de bytes
// Escritura en el archivoBloqueado
Files.write(archivoBloqueado.toPath(), arrayBytes, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING);
try{ sleep(1000); }catch (InterruptedException e) { e.printStackTrace(); }
lock = channel.lock();
}catch (IOException e){ }
cambioRealizado();
} else { try { sendChannel.write(-1); } catch (Exception e){} }
}
/*Desbloquear archivo */
private void unlockArchivo(){ if(bloqueado){try {
try { lock = channel.tryLock(); }catch (IOException ioe){}
} catch (OverlappingFileLockException e) { try { lock.release(); channel.close(); }catch (IOException ioe2){} }
archivoBloqueado = null; bloqueado = false; System.out.println("Archivo desbloquado");
cambioRealizado();
}else try { sendChannel.write(-1); } catch (Exception e){}
}
/*Busqueda y bloqueo de archivo con comando LOCK*/
private void lockArchivo(){
if(!bloqueado){ BuscadorArchivo find = new BuscadorArchivo();
archivoBloqueado = find.buscador(comando.substring(orden.length(), comando.length() ), new File("C:\\"));
if(archivoBloqueado != null) {
try{
accesoABloqueo = new RandomAccessFile(archivoBloqueado, "rws"); //aqui podemos acceder al archivo para leer y escribir en el
channel = accesoABloqueo.getChannel();
lock = channel.lock(); }catch (IOException e){}
bloqueado = true; System.out.println("Archivo bloqueado."); cambioRealizado(); }
else{ try { sendChannel.write(-1); } catch (Exception e){} }
}
}
private File buscarArchivo(){
BuscadorArchivo find = new BuscadorArchivo();
return find.buscador(comando.substring(orden.length(), comando.length() ), new File("C:\\")); }
/*Orden Realizada correctamente*/
private void cambioRealizado(){
comando = ""; orden = "";
String textoEnvio = "Done.";
byte[] arrayBytes = textoEnvio.getBytes();
try{ sendChannel.write(arrayBytes); } catch (IOException e) { System.out.println(e); }
}
void desbloquearCanal(){ try{ lock.release(); }catch(IOException e ){} }
}
Clase HiloEnvio
import java.net.*;
import java.io.*;
/**
* Clase HiloEnvio extiende de Thread y es la encargada de recibir el archivo encontrado y el canal con el cliente, que utiliza para enviar el archivo a destino
*
* @author Lorenzo31
* @version (a version number or a date)
*/
public class HiloEnvio extends Thread
{
private File archivo;
private Socket socketCliente = null;
private FileInputStream fileChannel = null;
private BufferedInputStream lectorArchivo = null;
private BufferedOutputStream sendChannel = null;
public HiloEnvio(Socket socketCliente, File archivo){ this.socketCliente = socketCliente; this.archivo = archivo;}
public void run() {
// send file
try{
byte [] mybytearray = new byte [(int)archivo.length()];
fileChannel = new FileInputStream(archivo);
lectorArchivo = new BufferedInputStream(fileChannel);
lectorArchivo.read(mybytearray,0,mybytearray.length);
sendChannel = new BufferedOutputStream(socketCliente.getOutputStream());
System.out.println("Sending " + archivo + "(" + mybytearray.length + " bytes)");
//envio archivo
sendChannel.write(mybytearray,0,mybytearray.length);
sendChannel.flush();
System.out.println("Done.");
}catch (IOException | NullPointerException e) { System.out.println("Interrumpido. ");
interrupt();
}
}
}
Clase BuscadorArchivo
import java.io.*;
import java.net.*;
public class BuscadorArchivo {
File archivoEncontrado = null;
boolean encontrado;
public BuscadorArchivo() { this.encontrado = false; /*siempre que se llama al buscador reinicia a false el boolean */ }
public File buscador(String nombre, File raiz){
if(!encontrado){ //si no esta encontrado entra en el for para buscar
File[] lista = raiz.listFiles();
if(lista != null) {
for(File elemento : lista) {
if (elemento.isDirectory()) {
buscador(nombre, elemento);
} else if (nombre.equalsIgnoreCase(elemento.getName()))
{
archivoEncontrado = elemento;
encontrado = true;
}
}
}
} else { return archivoEncontrado; }
return archivoEncontrado;
} //cierre buscador
}
Clase ClienteFicheros
import java.io.*;
import java.net.*;
import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths;
import java.nio.channels.FileChannel;
public class ClienteFicheros
{
public static void main(String[] args) throws IOException {
int bytesRead;
BufferedOutputStream bos = null;
Socket socketCliente = null;
PrintWriter salida = null;
String hostName = InetAddress.getLocalHost().getHostName();
/* Creamos un socket en el lado cliente, enlazado con un servidor que está en la misma máquina
que el cliente y que escucha en el puerto 4444 */
try{ socketCliente = new Socket(hostName, 4444);
System.out.println("servidor conectado:" + hostName);
//Obtenemos el canal de salida
salida = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socketCliente.getOutputStream())),true);
}catch(IOException e){
System.err.println("No puede establecer conexion");
System.exit(-1); }
BufferedReader stdIn = new BufferedReader(new InputStreamReader(System.in));
String linea = "";
/*El programa cliente no analiza los mensajes enviados por el usuario, simplemente los
* reenvia al servidor hasta que este se despide con Adios*/
while(!linea.equalsIgnoreCase("bye")){
do{
System.out.println("Introduce comando válido:");
//Leo la entrada del usuario
linea = stdIn.readLine();
//parámetros permitidos en la introducción de datos del usuario: lock unlock get put get "archivo"
}while (!linea.matches("[a-z][a-z][a-z] \".*\"") && !linea.matches("[a-z][a-z][a-z]") && !linea.matches("[l][o][c][k] \".*\"")
&& !linea.matches("[u][n][l][o][c][k] \".*\""));
//La envia al servidor
salida.println(linea);
if(!linea.equalsIgnoreCase("bye")){
OutputStream fos = null;
try {
//reciibr archivo
//Creamos array de bytes
byte [] mybytearray = new byte [1000000];
//Creamos objeto InputStream que abre la cadena de entrada para lectura del fichero que mande servidor
BufferedInputStream cadenaReceptor = new BufferedInputStream (socketCliente.getInputStream());
bytesRead = cadenaReceptor.read(mybytearray,0,mybytearray.length);
//}
//Si al ejecutar la orden el servidor no reenvia ningun fichero ni un texto vacio, por error de sintaxis ,
//manda un "Done." y el valor de bytesRead es 0 para identificarlo
//BufferedReader comprobar = new BufferedReader( new InputStreamReader(cadenaReceptor));
switch(bytesRead){
case 1: //1 valor que toma como mínimo un archivo Outputstream, significa archivo no encontrado o no buscado
System.out.println("Archivo no encontrado o comando erroneo"); break;
case -1: //-1 valor que toma al no recibir ningun archivo erroneo ni correcto, solo con BYE
System.out.println("Sesion finalizada"); break;
case 5: //0 indica orden realizada correctamente
System.out.println("Done."); break;
default:
Path direccionDestino = (Paths.get("C:/Mantequilla.txt")).toAbsolutePath();
File file = new File(direccionDestino.toString());
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos);
bos.write(mybytearray, 0 , bytesRead);
bos.flush();
fos.close();
System.out.println("File downloaded (" + bytesRead + " bytes read) at " + direccionDestino.toString() );
} //end switch
}catch(IOException e){ System.out.println("Error en la transmisión.");
if (fos != null) fos.close();
if (bos != null) bos.close();
if (socketCliente != null) socketCliente.close(); }
}
}
System.out.println("Sesión finalizada.");
// if (fos != null) fos.close();
if (bos != null) bos.close();
if (socketCliente != null) socketCliente.close();
}
}