Olá...
Tenho uma aplicação cliente-servidor. Nessa aplicação, o cliente faz upload de vídeos no servidor e pode fazer download de vídeos do repositório do servidor. Faço essa tranferência de dados via conexão TCP/IP...Sempre que o cliente faz upload de algum vídeo, além de enviar os dados do vídeo, envia um Objeto Propriedades, que encapsula propriedades autorais do vídeo...Sempre que ele faz download do vídeo, em seguida, ele baixa as propriedades do vídeo...
Para tanto, obtenho dosi tipos de fluxos de dados do meu socket um de Data e um do Object, assim:
private Socket socket;
private ObjectOutputStream saidaObjeto;
private ObjectInputStream entradaObjeto;
private DataInputStream entradaDado;
private DataOutputStream saidaDado;
public void conecta()throws ExcecaoDeIdentidadeNaoConfirmada, ExcecaoDeRede
{
this.socket = new Socket(controlador.getIPServidor(),controlador.getPortaServidor());
this.saidaObjeto = new ObjectOutputStream(socket.getOutputStream());
this.entradaObjeto = new ObjectInputStream(socket.getInputStream());
this.saidaDado = new DataOutputStream(socket.getOutputStream());
this.entradaDado = new DataInputStream(socket.getInputStream());
}
Ou seja, abro em paralelo essas duas espécies de fluxo de dados...
Abaixo tenho o método que faz a requisição e recebe arrays de bytes do servidor e já os escreve em um arquivo que crio.
public File recebeArquivoDeVideo(String nomeDoArquivo)throws ExcecaoDeRede,ExcecaoDeClienteNaoConectado
{
if(this.estahConectado)
{
try
{
Mensagem<String> requisicao = new Mensagem(TipoDeMensagem.REQUISICAO_ENVIO_DE_ARQUIVO_DE_VIDEO,nomeDoArquivo);
saidaObjeto.writeObject( requisicao );
saidaObjeto.flush();
File arquivo = controlador.getArquivoDeVideoTemporario(nomeDoArquivo);
Mensagem<Integer> mensagem = (Mensagem<Integer>)entradaObjeto.readObject();
if(mensagem.getTipoDeMensagem()==TipoDeMensagem.TRANSPORTE_DE_INFORMACAO_DE_TAMANHO_DE_ARQUIVO)
{
DataOutputStream saidaArquivo = new DataOutputStream(new FileOutputStream(arquivo));
//O servidor envia o tamanho do arquivo que está para enviar, empacotado em um Integer
int bytesParaReceber = ((Integer)mensagem.getDados()).intValue();
int tamanhoDoFragmento = 1024*128;
byte[] dados = new byte[tamanhoDoFragmento];
int bytesLidos;
long tempoInicial = System.currentTimeMillis();
while(bytesParaReceber>0)
{
//bytesLidos = (bytesParaReceber >= tamanhoDoFragmento ? tamanhoDoFragmento : bytesParaReceber);
if(bytesParaReceber >= tamanhoDoFragmento)
{
bytesLidos = tamanhoDoFragmento;
}
else
{
bytesLidos = bytesParaReceber;
dados = new byte[bytesLidos];
}
entradaDado.read(dados,0,bytesLidos);
saidaArquivo.write(dados,0,bytesLidos);
bytesParaReceber = bytesParaReceber - bytesLidos;
try
{
Thread.sleep(0,1);
}
catch(InterruptedException IE)
{
continue;
}
}
saidaArquivo.close();
return arquivo;
}
else
{
throw new ExcecaoDeRede();
}
}
catch(IOException IOE)
{
throw new ExcecaoDeRede();
}
catch(ClassNotFoundException CNFE)
{
throw new ExcecaoDeRede();
}
catch(Exception ex)
{
throw new ExcecaoDeRede();
}
}
else
{
throw new ExcecaoDeClienteNaoConectado();
}
}
Aqui tenho o método que recebe o objeto Propriedades do servidor.
public Propriedades recebePropriedadesDeVideo(String nomeDoArquivo)throws ExcecaoDeRede,ExcecaoDeClienteNaoConectado
{
if(this.estahConectado)
{
try
{
Mensagem<String> requisicao = new Mensagem(TipoDeMensagem.REQUISICAO_ENVIO_DE_PROPRIEDADES_DE_VIDEO,nomeDoArquivo);
saidaObjeto.writeObject(requisicao);
Mensagem<Propriedades> propriedades = (Mensagem<Propriedades>)entradaObjeto.readObject();//Nesta linha acusa o erro
return propriedades.getDados();
}
catch(IOException IOE)
{
IOE.printStackTrace();
throw new ExcecaoDeRede();
}
catch(ClassNotFoundException CNFE)
{
throw new ExcecaoDeRede();
}
}
else
{
//Excecao e cliente não conectado ao servidor
throw new ExcecaoDeClienteNaoConectado();
}
}
Pois é...Esses doi método são sempre chamados um em seqüência do outro...Primeiro eu recebo os dados do vídeo e em seguida as Propriedades dele.
Reparem que no método em que recebo os dados do vídeo, fico recebendo fragmentos dele. O número de bytes de cada fragmento é dado pela variável tamanhoDoFragmento...Se eu estipulo esse valor em 1024 (ou seja, 1KByte), tudo ocorre maravilhosamente bem...Se altero esse valor (é claro, tanto no servidor, quanto no cliente), ocorre uma Exceção muito estranha:
[color=red]java.io.StreamCorruptedException: invalid type code: B6[/color]
Queria entender porque isso ocorre...Estou fazendo algo errado?
Obrigado...