Olá a todos.
Sou, de certa forma, iniciante em java, e estou com uma dúvida num programa que fiz. Eu sei que existem tópicos específicos sobre programas cliente/servidor usando sockets como o meu, mas resolvi criar esse tópico aqui pois acredito que o problema no meu programa não é na troca de informações em si. O problema é o seguinte: o objetivo do programa é que exista um servidor capaz de fornecer a um cliente um arquivo ou dados sobre esse arquivo quantas vezes o cliente desejar. Para isso no programa cliente existe um menu onde o usuário escolhe que função vai usar e cada função envia um inteiro ao servidor dizendo a ele o que fazer. A função de enviar dados do arquivo ao cliente funciona perfeitamente, quantas vezes o cliente desejar. O porém é que a função de envio de arquivos funciona uma única vez. Após enviar o arquivo para o cliente, está ocorrendo algum erro e o programa encerra. Detalhe que o arquivo chega perfeitamente no cliente, o servidor só não consegue pegar o proximo inteiro correspondente a qual funcão ele deve executar em seguida. Segue os códigos:
Servidor:
package teste_servidor3;
import java.io.;
import java.net.;
import javax.swing.;
import java.util.;
import java.text.*;
public class Main {
static final int porta = 5050;                          //Define a porta a ser usada para a conexão.
static final int bloco = 1024 * 4;                      //Define o tamanho do bloco de bytes a ser enviado por vez, na trasferência.
public static void main(String[] args) {
try {
    System.out.println("Abrindo Socket...");
    ServerSocket server = new ServerSocket(porta);  //Cria um socket tipo servidor na porta especificada.
    System.out.println("Socket Aberto");
    JOptionPane.showMessageDialog(null, "Servidor Online.\n Aguardando conexão.");
    System.out.println("Aguardando Conexão...");
    int flag = 1;                                   //Variável de controle que mantem o servidor executando.
    while(flag == 1){                               //Permanece no loop até que flag seja modificado na função 'encerra'.
        Socket client = server.accept();            //Espera até que um cliente se conecte ao servidor.
        System.out.println("Conexão estabelecida com sucesso");
        int option;
        DataInputStream fromClient = new DataInputStream(client.getInputStream());
        DataOutputStream toClient = new DataOutputStream(client.getOutputStream());
      
        do{
            option = fromClient.readInt();          //Recebe do cliente a função que deve ser executada.
            System.out.println(option);
            switch(option){
                case 1: envia_arquivo(fromClient,toClient);  //Função responsável por enviar o arquivo ao cliente.
                    break;
                case 2: envia_dados(fromClient, toClient);          //Função responsável por enviar dados do arquivo ao cliente.
                    break;
                case 3: flag = encerra(client,server,fromClient,toClient);  //Função responsável por encerrar o servidor.
                    break;
                default: System.out.println("O servidor nao pode executar a requisicao.");
            }
        }while(option != 3);                        //Permanece no loop até que o cliente insira a opção 3.
    }
}catch (Exception e) {
    System.err.println("ERRO: "+e.getMessage());
}
}
static void envia_arquivo(DataInputStream fromClient, DataOutputStream toClient){
try{
String nome = fromClient.readUTF();             //Recebe do cliente o nome do arquivo que deve ser enviado.
System.out.println(nome);
//String diretorio = JOptionPane.showInputDialog(null, “Insira o diretório onde se encontra o arquivo no servidor.”);
File arquivo = new File(“C:\” + nome);
DataInputStream in = new DataInputStream(new FileInputStream(arquivo));
    long aux = arquivo.length();                    //Pega o tamanho do arquivo.
    String aux2 = String.valueOf(aux);
    toClient.writeUTF(aux2);                        //Envia o tamanho do arquivo para o cliente.
    System.out.println(aux2);
    int tamanho = Integer.parseInt(aux2);
    System.out.println("Enviando arquivo...");
    int pacote = bloco;
    int count = tamanho;
    byte[] buffer = new byte[pacote];               //Cria um buffer que armazenará blocos de bytes do arquivo a serem enviados.
    while (count > -1){                             //Permanece enviando ao cliente até que 'count' seja 0.
        int caracter = in.read(buffer, 0, pacote);
        toClient.write(buffer, 0, caracter);
        count = count - caracter;
        if(count == 0) break;
    }
    toClient.flush();
    in.close();
    System.out.println("Arquivo enviado com sucesso.");
}catch (Exception e) {
    System.err.println("ERRO: "+e.getMessage());
}
}
static void envia_dados(DataInputStream fromClient, DataOutputStream toClient){
try{
String nome = fromClient.readUTF();             //Recebe do cliente o nome do arquivo sobre o qual ele deseja informações.
//String diretorio = JOptionPane.showInputDialog(null, “Insira o diretório onde se encontra o arquivo no servidor.”);
File arquivo = new File(“C:\” + nome);
    long lastModified = arquivo.lastModified();     //Pega a data na qual o arquivo foi modificado pela ultima vez.
    DateFormat formato = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss"); //Coloca a hora no formato especificado.
    String data = formato.format (new Date(lastModified));
    toClient.writeUTF(data);                        //Envia a data para o cliente.
}catch (Exception e) {
    System.err.println("ERRO: "+e.getMessage());
}
}
static int encerra(Socket client,ServerSocket server, DataInputStream fromClient,DataOutputStream toClient){
int flag = 1;
try{
toClient.close();                               //Fecha a stream de saida.
fromClient.close();                             //Fecha a stream de entrada.
client.close();                                 //Fecha o socket do cliente.
int confirmacao= JOptionPane.showConfirmDialog(null, “Deseja fechar o servidor?”); //Confirma o encerramento do servidor.
    if(confirmacao == JOptionPane.YES_OPTION) {
        System.out.println("Servidor encerrado.");
        server.close();                             //Se sim, fecha o socket servidor e torna flag igual a '0'.
        flag = 0;
    }
    else{
        flag = 1;                                   //Se não, mantem flag igual a '1', o que permitira que outro cliente se conecte ao servidor.
        System.out.println("Aguardando conexão...");
    }
}
catch(Exception e){
    System.err.println("ERRO: "+e.getMessage());
}
return flag;
}
}
Cliente:
package teste_cliente3;
import java.io.;
import java.net.;
import javax.swing.*;
public class Main {
static final int porta = 5050;                                  //Define a porta a ser usada para a conexão.
static final int bloco = 1024 * 4;                              //Define o tamanho do bloco de bytes a ser enviado por vez, na trasferência.
public static void main(String[] args) {
int resposta = JOptionPane.showConfirmDialog(null, "Deseja se conectar ao servidor?" );
if(resposta == JOptionPane.YES_OPTION){                     //Oferece ao cliente a opção de se conectar ao servidor.
    Socket clientSocket = connect();                        //Chama a função responsável por estabelecer a conexão.
    try {
        System.out.println("Conexão estabelecida com sucesso.");
        DataOutputStream toServer = new DataOutputStream(clientSocket.getOutputStream());
        DataInputStream fromServer = new DataInputStream(clientSocket.getInputStream());
        menu(toServer, fromServer, clientSocket);           //Chama a função que oferece as opções disponíveis ao cliente.
        toServer.close();                                   //Fecha a stream de saída.
        fromServer.close();                                 //Fecha a stream de entrada.
        clientSocket.close();                               //Fecha o socket cliente.
    }catch(Exception e){
        System.err.println("Erro: " + e.getMessage());
    }
}
else{
    JOptionPane.showMessageDialog(null, "Fim da execução.");
    System.exit(0);
}
}
static Socket connect(){
Socket clientSocket = null;                                 //Declara o socket cliente.
try {
System.out.println(“Abrindo Socket…”);
String ip = JOptionPane.showInputDialog(null, “Insira o IP do servidor.”);  //Pega o IP do servidor.
clientSocket = new Socket(ip, porta);                   //Se conecta ao servidor na porta pré definida.
}
catch(Exception e){
System.err.println("Erro: " + e.getMessage());
}
return clientSocket;
}
static void menu(DataOutputStream toServer, DataInputStream fromServer, Socket clientSocket){
int opcao;
try{
do {
opcao = Integer.parseInt(javax.swing.JOptionPane.showInputDialog(“Escolha uma das opções abaixo:\n” +
“1 - Transferência de arquivo.\n” +
“2 - Data de modificação do arquivo.\n” +
“3 - Encerrar a conexão e sair.\n”));
switch (opcao){
case 1: transferencia(toServer, fromServer, clientSocket); //Função responsável por receber o arquivo do servidor.
break;
case 2: dado_arquivo(toServer, fromServer);                //Função responsável por receber dados sobre o arquivo.
break;
case 3: toServer.writeInt(3);                              //Manda para o servidor o identificador de que o cliente deseja encerrar a conexão.
JOptionPane.showMessageDialog(null, “Conexão encerrada.”);
break;
default: JOptionPane.showMessageDialog(null, “A opção digitada é invalida.\n Escolha uma opção válida para continuar.”);
}
}while(opcao != 3);                                                 //Continua no loop até que o cliente insira a opção ‘3’.
}catch(Exception e){
System.err.println("Erro: " + e.getMessage());
}
}
static void transferencia(DataOutputStream toServer, DataInputStream fromServer, Socket clientSocket){
try{
toServer.writeInt(1);                                  //Manda para o servidor o identificador de que o cliente deseja transferir um arquivo.
    String nome = JOptionPane.showInputDialog(null, "Insira o nome do arquivo que deseja baixar.");
    toServer.writeUTF(nome);                               //Manda para o servidor o nome do arquivo a ser baixado.
    System.out.println(nome);
    //String diretorio = JOptionPane.showInputDialog(null, "Insira o diretorio onde deseja salvar o arquivo.");
    DataOutputStream out = new DataOutputStream (new FileOutputStream("D:\\" + nome));
    DataInputStream in = new DataInputStream(clientSocket.getInputStream());
    String size = fromServer.readUTF();                    //Recebe do servidor o tamanho do arquivo.
    System.out.println(size);
    int tamanho = Integer.parseInt(size);
    int pacote = bloco;
    int count = tamanho;
    byte[] buffer = new byte[pacote];                       //Cria um buffer para receber o arquivo.
    System.out.println("Recebendo arquivo...");
    while(count > -1) {                                     //Permanece no loop até que contador se torne '0'.
        int readByte = in.read(buffer, 0, pacote);
        out.write(buffer, 0, readByte);                     //Escreve os blocos de bytes recebidos no arquivo criado.
        count = count - readByte;
        if (count == 0) break;
    }
    System.out.println("Arquivo recebido com sucesso.");
    out.flush();
    out.close();                                            //Fecha a stream de saida.
    in.close();                                             //Fecha a stream de entrada.
    JOptionPane.showMessageDialog(null, "Arquivo recebido com sucesso.");
}catch(Exception e){
    System.err.println("Erro: " + e.getMessage());
}
}
static void dado_arquivo(DataOutputStream toServer, DataInputStream fromServer){
try{
toServer.writeInt(2);                                   //Manda para o servidor o identificador de que o cliente deseja dados arquivo.
    String nome = JOptionPane.showInputDialog(null, "Insira o nome do arquivo.");
    toServer.writeUTF(nome);                                //Manda para o servidor o nome do arquivo.
    String data = fromServer.readUTF();                     //Recebe do servidor, a data de modificação do arquivo.
    JOptionPane.showMessageDialog(null, "A data de modificação do arquivo é: \n" + data );
}catch(Exception e){
    System.err.println("Erro: " + e.getMessage());
}
}
}