Transferir vários arquivos do servidor para cliente via socket (download)

Pessoal, sou iniciante no que diz respeito à Sockets e estou desenvolvendo um sistema Cliente/Servidor. O problema é o seguinte, com o código abaixo eu consigo fazer o download de um arquivo, mas preciso fazer o download de vários arquivos e não sei como mudar o código para isso. Segue código:

SERVIDOR



public class FileServer {
	
	private final int BLOCK_SIZE = 1024;
	/* Guarda a referencia para o socket do cliente */
	private Socket clientSocket;
	private ObjectOutputStream output;
	private ObjectInputStream input;
	private FileInputStream fileReader;
	private String [] fileNames;

	public FileServer( int port, String sharedDirectory ) {

                try {
                        //Waiting Connections.
                    // criando um socket que fica escutando a porta passada como parametro.
                        ServerSocket serverSocket = new ServerSocket( port );

                        
                  //cria uma conexão e o servidor aceita o cliente
			clientSocket = serverSocket.accept();

			

                        //Sending files list.
			File directory = new File( sharedDirectory );
			fileNames = directory.list();
                        //preparar o outputstream para enviar o arquivo
			output = new ObjectOutputStream( clientSocket.getOutputStream() );
			output.writeObject( fileNames );
			
                        //Wainting request.
			input = new ObjectInputStream( clientSocket.getInputStream() );
			String fileName = (String) input.readObject();
			System.out.println( "SENDING FILE: " + fileName );
			
                        //Send requested file.
			File fileToUpload = new File( sharedDirectory + File.separator + fileName );
			this.sendFile( fileToUpload );
			
                      
			//Close resourses.
			input.close();
			clientSocket.close();
			System.out.println("FINISHED SENDING!");
                } catch ( IOException ioex ) {
                        ioex.printStackTrace();
                } catch ( ClassNotFoundException cnfex ) {
			cnfex.printStackTrace();
		}
                

	}
	
	private void sendFile( File toSend ) throws FileNotFoundException, IOException {
		this.fileReader = new FileInputStream( toSend );
//long tamanhoArquivo = enviarPara.comprimento
		long fileSize = toSend.length();
                //a variavel  timesToIterate (tempo de iteração) divide o tamanho do arquivo pelo (tamanho do bloco)BLOCK_SIZE, no caso 1024 permitindo sobras
		int timesToIterate = (int) fileSize / BLOCK_SIZE;
		 //a variavel  bytesForLastPackage ( bytes por último pacote) divide o tamanho do arquivo pelo tamanho do BLOCK_SIZE, no caso 1024 admite os restos
		//recebe os restos
                
                int bytesForLastPackage = (int) fileSize % BLOCK_SIZE;
		if( bytesForLastPackage > 0 ) timesToIterate++;
		Message m = null;
             
		

                byte [] bytes;
                //percorrer o arquivo e ir enviando para cliente   
		for ( int i = 1; i < timesToIterate; i++ ) {
                 // cria um buffer de 1024 bytes para o envio //BLOCK_SIZE
			bytes = new byte[BLOCK_SIZE];
			fileReader.read( bytes );
			m = new Message( toSend.getName(), timesToIterate );
			m.setBytes( bytes );
			m.setPackageNumber( i );
			output.writeObject( m );
			output.flush();
		}
		//SENDING LAST PACKAGE
		if ( bytesForLastPackage > 0 ) {
			System.err.println("Sending LAST package with " + bytesForLastPackage + " bytes.");
			bytes = new byte[bytesForLastPackage];
			fileReader.read( bytes );
			m = new Message( toSend.getName(), timesToIterate );
			m.setBytes( bytes );
			m.setPackageNumber( timesToIterate );
			output.writeObject( m );
			output.flush();
		}
		this.fileReader.close();
		
	}
	
}


Desde já agradeço!

Oi, coloque as tags entre code…

Versão 1 - Modifiquei o arquivo main:

FileClient client = new FileClient(ip, port);
            while (true) {
                ui.receiveFile(client);
                System.out.print("Press Y to download another file or N to exit.");
                String s = System.console().readLine();
                if (!s.equalsIgnoreCase("y")) {
                    break;
                }
            }
            client.close();

Versão 2 - Criei novos métodos.

    private String getMultipliFileName(String[] fileNames) {
        System.out.println("================FILE LIST================");
        for (String fileName : fileNames) {
            System.out.println(fileName);
        }
        System.out.println("=========================================");
        System.out.print("Write files names separated with ; ");
        String fileName = System.console().readLine();

        return fileName;
    }

    private String getDirectory() {
        System.out.print("Write the diretory path to store file: ");
        String diretory = System.console().readLine();
        return diretory + File.separator;
    }

    private void receiveMultiplyFile(FileClient client) {
        String fileName = this.getFileName(client.getAvailableFiles());
        String dir = getDirectory();
        String[] files = fileName.split(";");
        for (String f : files) {
            try {
                boolean fine = client.receiveFile(dir + f);
                if (fine) {
                    System.out.println("DOWNLOAD DONE!!!!");
                }
            } catch (IOException ex) {
                System.err.println("ERRRRRROR 1!!!");
            } catch (ClassNotFoundException ex) {
                System.err.println("ERRRRRROR 2!!!");
            }
        }
    }

Espero que alguma versão te ajude.

Cara, muito boa a sua dica, mas em ambos os casos não funcionou o download do segundo aquivo, será que preciso modificar alguma coisa na minha classe servidor também??? Porque estou fechando a conexão assim que terminna a tranferencia de arquivo, como ficaria isso pra varios arquivos???

Bom Jac, eu vi que o FileServer fecha a conexão. Para conseguir te ajudar melhor teria que fazer a aplicação rodar aqui, mas não consegui.
Isso não é a melhor solução mas tente alterar o código da versão 1 para:

            FileClient client = null;
            while (true) {
                client = new FileClient(ip, port);
                ui.receiveFile(client);
                System.out.print("Press Y to download another file or N to exit.");
                String s = System.console().readLine();
                if (!s.equalsIgnoreCase("y")) {
                    break;
                }
            }
            client.close();

Pelo que eu vi, é necessário alterar a forma como o servidor lida com as conexões para solução ideal do problema.

Então, no meu método private void sendFile eu determino a transferencia de um arquivo em bytes de 1024, acho que o problema é: o servidorenviao primeiro arquivo sem nenhum problema, quando vai pegar o segundo arquivo dá pau, será que o problema é nesse método?

1. Use a tag code para postar códigos:
http://www.guj.com.br/posts/list/50115.java

  1. Entenda exatamente como o TCP/IP funciona. Para isso, você tem que montar um protocolo da sua aplicação. É uma péssima alternativa usar ObjectInputStream e ObjectOutputStream: http://www.guj.com.br/posts/list/136538.java A forma que você está usando provavelmente desperdiça uma quantidade absurda de banda.

  2. Considere fortemente a possibilidade de usar um protocolo para transferência de arquivos já existente, como o TFTP ou o FTP:
    http://www.faqs.org/rfcs/rfc1350.html

  3. Fica mais difícil dar esse tipo de suporte se você tiver que se adequar a um servidor. Você pode alterar o protocolo em ambas as pontas?

Caras agradeço muito pela ajuda, principalmente a vc bzy, cara com as dicas que você me deu e mais algumas poucas alterações o treco aqui funcionou, ViniGodoy, ótimos links esse que vc me mandou, vou ler todos e me aprofundar um pouco mais, valeu mesmo

Balela,
á transferencia dos arquivos dá certo em parte, tipo
o arquivo é tranferido belezinha mas se o primeiro arquivo tiver tipo 34 kb e o segundo um pouco mais, sei lá, 50 kb digamos, só é tranferido do segundo arquivo os mesmo 34 bytes do primeiro a outra parte é perdida, help