What is the best way to send XML converted to a byte array over TCP, then translate the response back to readable XML?

2k views Asked by At

I've been asked to write a solution that converts XML to a byte array to be sent as a request to a .Net service over straight TCP along with other parameters the service requires. The service returns XML in a byte array format. In the following solution, I've tried to implement these principles:

  1. Open a socket.
  2. Open an input stream and output stream to the socket.
  3. Read from and write to the stream according to the server's protocol.
  4. Close the streams.
  5. Close the socket.

Note that I'm calling the code below from a main program that converts a XML file to a byte array for the requestData parameter and closes the socket opened by creating an instance of the class. In the output, I'm getting a list of values that look like [B@60076007.

My questions are: Is the output example above in a byte array format that needs converted back to XML?, If so, is there a suggestion on how to do this? and Is there a better way to organize this code? Like should the send and receive be in separate functions? Thank you for the time of anyone willing to respond.

public class  TCPTest implements Closeable {


private static final Logger logger = Logger.getLogger( TCPTest.class);

private Socket socket;

public  TCPTest(String host, int port) throws IOException {
    this(new Socket(host, port));
}

public  TCPTest(Socket s) {
    this.socket = s;
}

public void send TCPRequest(int testId, String method, byte[] requestData, boolean sendLength) throws IOException {

    socket.setSoTimeout(40000);

    DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
    DataInputStream dis = new DataInputStream(socket.getInputStream());

    try 
    {
        dos.write(testId);
        dos.writeBytes(method);

        dos.write(requestData); // write the message
        System.out.println("length of request: " + requestData.length);

        if (sendLength) {
            String lengthDesc = "LEN*";
            byte[] lengthDescBytes = lengthDesc.getBytes("US-ASCII");

            dos.write(lengthDescBytes);

            dos.write(requestData.length);
        }

    } catch (UnknownHostException e) {
        System.err.println("Unable to find host: 3125");
    } catch (IOException e) {
        System.err.println("Couldn't get I/O for the connection to: 3125");
    }

    try 
    {
        int lengthResponse = dis.read(); // get length of incoming message
        System.out.println("length of response: " + lengthResponse);

        while (lengthResponse > 0) {
            byte[] message = new byte[lengthResponse];
            System.out.println(message);

            dos.write(message, 0, lengthResponse);

        }

    } catch (EOFException e) {
        System.err.println("Input stream ended before all bytes read");
    } catch (IOException e) {
        System.err.println("I/O failed on the connection to: 3125");
    }

    dos.flush();
    dos.close();
}

@Override
public void close() throws IOException {
    this.socket.close();
}

}

1

There are 1 answers

0
Antoniossss On

So basicly the incoming data is a byte[] because that is what string form says about that object [B@60076007, at least the [B part.

So now, as the XML is just simple String you can convert your byte array to as String using String(byte[] bytes, Charset charset) where you have to provide encoding that will be used for conversion.

From the string form you can create any other XML representation (w3c, dom4j etc) that you will need, if this is not sufficient.

Besides after looking into your code, I can see that you are not reading the server output at all.

int lengthResponse = dis.read(); // get length of incoming message

no, this line reads onli first byte (not integer) from the stream. Integers are 4 bytes length.

 byte[] message = new byte[lengthResponse];
    System.out.println(message);

you are creating new byte array (buffer) whitch is good, but you are never writing to it (by reading from the input stream). After that, you are printing the results of message.toString() method.

You need to read the whole message first,convert and store it later.

Pseudocode:

    InputStream in;
    byte[] buff=new byte[your_length]

    in.read(buff) //this line will read your_length bytes from the input stream
    String message=new String(buff,ProperCharset); //convert to string
    sysout(message); // print it
    //do whatewer you like eg, store to your DataOutputStream with 
    // out.write(message.getBytes(ProperCharset));
    // or directly out.write(buff);