Search code examples
javaxmlsocketstcp

Not receiving response sending XML via TCP/IP using Java


I'm new to Java (basically had to learn it on the fly for this project), but I'm trying to send an XML command to a server (a sensor in my lab) to get some data from it. To do this, I've written a Java program and I'm running it from the command line. The connection establishes successfully, and (I think) the message is being successfully sent - however it is getting stuck "Awaiting a Response".

Here's my Java code for a reference. I got most of this from a client/server TCP tutorial, and adjusted the IP, port, and outgoing message accordingly. Again, I'm very new to this, so any help is appreciated.

// Java Socket Example - Client

import java.io.IOException; // Throws exception if there is an issue with input or output
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress; // This class represents an Internet Protocol address
import java.net.Socket;
import java.net.UnknownHostException;

/**
* This class implements java socket Client
*/

public class SocketClientExample {
	public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException, InterruptedException {
		// get the localhostIP address, if server is running on some other IP, use that 
		System.out.println("Attempting connection to GE Reuter Stokes");
		InetAddress host = InetAddress.getByName("10.212.160.4"); // IP GOES HERE
		Socket socket = null; // start out as null, protocal
		ObjectOutputStream oos = null; // This will change, just setting default
		ObjectInputStream ois = null;
		// establish the socket connection to the server
		socket = new Socket("10.212.160.4", 3010); // 9876 is just the port number
		System.out.println("Made it past Socket Initialization");
		// write to socket using ObjectOutputStream
		oos = new ObjectOutputStream(socket.getOutputStream()); // new instance of OOS that will write to the socket
		System.out.println("Sending request to Socket Server"); 
		// Initializing request string
		String request = new String("0xF00041 " + "<Discovery><CommChannelName>Unknown</CommChannelName></Discovery>");
		// In our version, this is where the XML script would go
		oos.writeObject(request);
		System.out.println("Request was sent. Awaiting response.");
		// read the server response message
		ois = new ObjectInputStream(socket.getInputStream());
		// convert the response into a string
		String message = (String) ois.readObject();
		System.out.println("Message: " + message);
		// close your resources
		ois.close();
		oos.close();
		Thread.sleep(100);
	}
}

It's more than likely something with the sensor - but I figured it wouldn't hurt to have a second set of eyes on the code.


Solution

  • The sensor expects the XML to be preceded by a binary 5-byte header, but you are sending the header as an 8-character hex encoded string instead.

    Also, you are using ObjectOutputStream and ObjectInputStream, which are meant for serializing Java objects, but you are not sending/reading Java objects. So these are the completely wrong stream classes to use.

    So, your code is not sending what the sensor is expecting, so it will not receive your request correctly, let alone send a response that you can receive.

    Try something more like this instead (assuming the sensor sends back a response in a similar header+XML format as the request):

    import java.io.IOException;
    import java.io.DataOutputStream;
    import java.io.DataInputStream;
    import jva.io.BufferedInputStream;
    import java.net.Socket;
    import java.net.UnknownHostException;
    import java.nio.charset.StandardCharsets;
    import java.nio.ByteBuffer;
    
    public class SocketClientExample {
        public static void main(String[] args) throws UnknownHostException, IOException, ClassNotFoundException, InterruptedException {
            System.out.println("Attempting connection to GE Reuter Stokes");
    
            // establish the socket connection to the server
            // using the local IP address, if server is running on some other IP, use that 
            Socket socket = new Socket("10.212.160.4", 3010);
            System.out.println("Socket Connected");
    
            // write to socket using OutputStream
            DataOutputStream dos = new DataOutputStream(socket.getOutputStream());
    
            // Initializing request content
            byte[] request = "<Discovery><CommChannelName>Unknown</CommChannelName></Discovery>".getBytes(StandardCharsets.UTF_8);
    
            // DataOutputStream.writeInt() writes in big endian and
            // DataInputStream.readInt() reads in big endian.
            // using a ByteBuffer to handle little endian instead.
    
            byte[] header = new byte[5];
            ByteBuffer buf = ByteBuffer.wrap(header, 1, 4);
            buf.order(ByteOrder.LITTLE_ENDIAN);
    
            // Initializing request header
            header[0] = (byte) 0xF0;
            buf.putInt(request.length);
    
            System.out.println("Sending request to Socket Server"); 
    
            // Sending request
            dos.write(header);
            dos.write(request);
            dos.flush();
    
            System.out.println("Request was sent. Awaiting response.");
    
            // read from socket using InputStream
            DataInputStream dis = new DataInputStream(new BufferedInputStream(socket.getInputStream()));
    
            // Read response header
            dis.readFully(header);
            buf.flip();
    
            // Read response content
            byte[] response = new byte[buf.getInt()];
            dis.readFully(response);
    
            // convert the content into a string
            String message = new String(response, StandardCharsets.UTF_8);
            System.out.println("Message: " + message);
    
            // close your resources
            dis.close();
            dos.close();
            socket.close();
    
            Thread.sleep(100);
        }
    }