Olá galera estou com um problema fiz um socket para se conectar com uma leitora de acesso fisico , a comunicaçõ entre leitora (servidor) e cliente é feita através de array de bytes,
o socket q eu utilizo é por meio do protocolo tcp/ip, o problema é q nem sempre vou saber o tamanho do array de bytes de resposta, e encontro problemas de estouro de array, há alguma maneira de eu saber previamente o tamanho da resposta para não ficar estanciando toda hora o array??
gratoo…
Ler array de bytes de um socket servidor
14 Respostas
Você pode optar em criar vários pacotes de tamanhos fixos para enviar toda a mensagem, ou até mesmo, antes de enviar a informação desejada, envia primeiro um valor inteiro que corresponde ao tamanho total da sua mensagem. Daí você instancia o array por completo e depois é só armazenar.
[]'s.
Como é o protocolo dessa leitora? Tipicamente, protocolos binários enviam algum tipo de cabeçalho de tamanho fixo, indicando o tamanho do array de bytes.
A leitora trabalha com protocolos tcp/ip , udp, rs422, mas estou utilizando o protocolo tcp/ip , e a respeito do cabeçalho não envia nada
olha o codigo que estou utilizando.
package socketpronto;
import java.io.*;
import java.net.*;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
/**
*
* @author Pedro Benavalli
*/
public class Cliente extends JFrame{
private JTextField enter;
private JTextArea display;
DataOutputStream output;
DataInputStream input;
byte [] message;
public Cliente(){
super("Socket Cliente");
Container c = getContentPane();
enter = new JTextField();
enter.setEnabled(true);
enter.addActionListener(
new ActionListener(){
public void actionPerformed(ActionEvent e){
if (!enter.getText().equals(null))
sendData(e.getActionCommand());
}
}
);
c.add(enter,BorderLayout.NORTH);
display = new JTextArea();
c.add(new JScrollPane(display), BorderLayout.CENTER);
setSize(300,150);
setVisible(true);
enter.requestFocus();
}
public String byteToString(byte[] parametro){
String resultado = "";
for (int i = 0; i < parametro.length; i++){
if (parametro[i] < 0 )
resultado = resultado + (Integer.toHexString(256+parametro[i]).toUpperCase());
if (parametro[i] < 16){
resultado += "0";
resultado += (Integer.toHexString(parametro[i]).toUpperCase());
}
}
return resultado;
}
private void sendData(String data){
try{
Socket client;
String host = "192.168.0.52";
int porta = 11010;
display.setText("Tentando a conexão \n");
client = new Socket(InetAddress.getByName(host),porta);
display.append("Conectado em: " + client.getInetAddress());
output = new DataOutputStream(client.getOutputStream());
output.flush();
input = new DataInputStream(client.getInputStream());
display.append("\n Adquirindo I/O streams ");
enter.requestFocus();
byte[] b = new byte[data.length() / 2];
try {
String s1;
int j=0;
for(int i = 0; i < data.length(); i += 2)
{
s1 = data.substring(i, i + 2);
b[j] = (byte)Integer.parseInt(s1, 16);
j++;
}
}
catch(NumberFormatException ex) {
ex.printStackTrace();
}
catch(StringIndexOutOfBoundsException ex){
ex.printStackTrace();
}
output.write(b);
output.flush();
System.out.println("Aqui");
input.readFully(b) ;
message = b;
output.close();
input.close();
client.close();
enter.setText(null);
// for(int i = 0 ; i< u.length ; i++)
System.out.print("|"+ byteToString(u));
display.append("\nILV enviado: " + data);
display.append("\n ILV recebido: " + byteToString(message));
}
catch(IOException op){
display.append("\n Erro ao escrever o objeto.");
}
}
public static void main(String Args[]){
Cliente app = new Cliente();
app.addWindowListener(
new WindowAdapter(){
@Override
public void windowClosing(WindowEvent e){
System.exit(0);
}
}
);
}
}
O codigo é esse e ele funciona perfeitamente com comandos que a resposta é do mesmo tamanho que o envio, se for diferente tenho que istanciar outro array para leitura, o problema é que nem sempre sei o tamnho do array de resposta...
como por exemplo listar todas as bases de dados, o array pode vir de n maneiras ... alguma solução??
Perguntei sobre o protocolo da leitora, não sobre o protocolo de transmissão de dados.
Quando vc envia um comando, (como esse que vc citou) como é o formato de retorno? Baseado em texto? Binário? Tem algum terminador, como \n \0?
A entao
o retorno é um array de bytes, e nao tem terminador de inicio ao fim sao bytes
E como vc interpreta esse retorno?
Eu tenho um tabelinha com possiveis respostas por exemplo se eu pingo a leitora com {0x08,0x00,0x00} a resposta devera ser
id_ comando, lenght_comando, request_status = {0x08,0x01,0x00} , porem em comandos por exemplo pra listar em que diretorio esta tal arquivo a sequencia em bytes ascii pode variar e não vejo maneiras de como istanciar o array de resposta para tal, só na tentativa e erro…
Ué, o campo length_comando não informa o tamanho contando os arrays?
entao, mas para ver o campo lenght primeiro eu precizo instanciar o vetor para guardar a resposta completa
Não, se suas mensagens sempre começam por:
id_ comando, lenght_comando
Você tem que ter 2 variáveis para esses 2 valores. Faça a leitura delas separadamente.
Depois de ler o length, você então cria o vetor, e lê o resto.
Sim, mas como farei isso, teria que abrir e fechar o socket 3 vezes para paegar toda resposta?
ou a outra maneira, pois qdo dou input.read(byte[],inicio,qtd_bytes) mais de uma vez a segunda resposta só vem bytes nulos, tentei o metodo reset() mais nem deu, tem alguma outra maneira??
Há o id do comando , o tamanho e a resposta, vem no mesmo array de bytes.
Antes do seu read, faça outros dois reads... Não precisa fechar o socket entre as leituras.
int idComando = input.read();
//Os dois primeiros bytes já foram lidos
int len = input.read() - 2;
byte[] buffer = new byte[len];
input.read(buffer,inicio,len)
Se cada valor desses tem mais de 2 bytes, faça as contas de acordo, e use o read apropriado. Use para isso o DataInputStream.
A questão é que você sabe que sempre antes dos arrays haverá esses dois campos. Por isso, faça a leitura deles separadamente. A informação de um deles te permite ler a parte variável com segurança.
Certo, resolvido…
vlw Vinii