sexta-feira, 31 de outubro de 2008

Transferir bytes de um lado pro outro

Quando você quer transferir bytes de um lado pro outro via socket você pode utilizar várias estratégias, eu criei dois Iterators para facilitar esta tarefa.


Trecho da classe que envia

Socket s = new Socket("localhost", 8888);
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
byte[] nome = { 1, 2, 3, 4, 5, 6, 7 };

ByteArrayInputStream bytArrIn = new ByteArrayInputStream(nome);

SenderInputStreamIterator it = new SenderInputStreamIterator(in, out, bytArrIn);
while (it.hasNext()) {
byte[] b = (byte[]) it.next();
System.out.println(b[0]);
}



Trecho da classe que recebe

ServerSocket serv = new ServerSocket(8888);
Socket s = serv.accept();
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();

ByteArrayOutputStream byteArrOut = new ByteArrayOutputStream();
ReaderInputStreamIterator it = new ReaderInputStreamIterator(in, out);
while (it.hasNext()) {
byte[] b = (byte[]) it.next();
System.out.println(b[0]);

}





/**
* Classe criada para receber as informações enviadas pelo
* SenderInputStreamIterator.

*
* Oquê acontece na verdade é que esta classe pergunta diz: Tem mais? Então
* manda!
*
* @author Clayton.Passos
*
*/
public class ReaderInputStreamIterator implements Iterator {
private static final int BUFFER_SIZE = 1;
private DataInputStream dataIn;
private DataOutputStream dataOut;
private byte[] buffer = new byte[BUFFER_SIZE];

/**
*
* @param in
* Canal de comunicação de entrada de dados, utilizado para pedir
* mais informações para o SenderInputStreamIterator através do
* hasNext(). Também é utilizado pelo next() par ler as
* informações que o SenderInputStreamIterator está enviando.
*
* @param out
* Canal de comunicação utilizado para pedir mais informações ao
* SenderInputStreamIterator
*/
public ReaderInputStreamIterator(InputStream in, OutputStream out) {
this.dataIn = new DataInputStream(in);
this.dataOut = new DataOutputStream(out);
}

public boolean hasNext() {
try {
// Tem mais informações/bytes?
dataOut.writeByte(TransferProtocol.hasNext);
byte hasNext = dataIn.readByte();

switch (hasNext) {
case TransferProtocol.yesHasNext:
return true;
case TransferProtocol.noHasNext:
return false;
default:
throw new IllegalStateException("TransferProtocol unexpected");
}

} catch (Exception e) {
throw new IllegalStateException(e);
}
}

public Object next() {
try {
// Se tem mais informações/bytes? Então manda.
dataIn.readFully(buffer);
return buffer;
} catch (Exception e) {
throw new IllegalStateException(e);
}
}

/**
* Not implemented, and in real case... you don´t implement this method
*/
public void remove() {
throw new IllegalStateException("Not implemented");
}
}






/**
* Classe destinada a enviar as informações contida no InputStream para a saída
* de dados sob demanda.

* Oquê acontece na verdade é que esta classe fica esperando a
* ReaderInputStreamIterator perguntar: Tem mais?
*
*

* Dialogo:
* Reader: Tem alguma coisa ai pra mim? Tem mais?
* Sender: Tenho, Toma!
*

*
* @author Clayton.Passos
*
*/
public class SenderInputStreamIterator implements Iterator {
private static final int BUFFER_SIZE = 1;
private DataInputStream dataIn;
private DataOutputStream dataOut;
private int bytesRead;
private byte[] buffer = new byte[BUFFER_SIZE];
private ByteArrayInputStream byteArrIn;

/**
*
* @param in
* Canal de comunicação para que o hasNext saiba que o
* ReaderInputStreamIterator está pedindo mais informações
* @param out
* Canal de comunicação para que o next() possa enviar a
* informação
*
* @param byteArrIn
* informações a serem enviadas e recebidas pelo
* ReaderInputStreamIterator
*/
public SenderInputStreamIterator(InputStream in, OutputStream out,
ByteArrayInputStream byteArrIn) {
this.dataIn = new DataInputStream(in);
this.dataOut = new DataOutputStream(out);
this.byteArrIn = byteArrIn;
}

public boolean hasNext() {
try {
// Reader está pedindo mais informações/bytes?
byte hasNext = dataIn.readByte();
if (hasNext == TransferProtocol.hasNext) {
bytesRead = byteArrIn.read(buffer);
// Se tem, então avisa que tem
if (bytesRead != -1) {
dataOut.write(TransferProtocol.yesHasNext);
dataOut.flush();
return true;
// Se não tem, então avisa que não tem
} else {
dataOut.writeByte(TransferProtocol.noHasNext);
dataOut.flush();
return false;
}

} else {
throw new IllegalStateException("TransferProtocol unexpected");
}

} catch (Exception e) {
throw new IllegalStateException(e);
}
}

public Object next() {
try {
// Manda mais informações/bytes
dataOut.write(buffer);
dataOut.flush();
} catch (Exception e) {
throw new IllegalStateException(e);
}
return buffer;
}

/**
* Not implemented, and in real case... you don´t implement this method
*/
public void remove() {
throw new IllegalStateException("Not implemented");
}
}

Nenhum comentário: