2

I am working with java and I am sending data to a PHP page. The goal is to send and store an object and then retrieve that object at a later time. As for now I am simply sending data and then having it echoed back. The response isn't quite what I send. First off, the response always starts with an ascii 32 (or space character). After that, sending an integer works up to 127. After that not only is the response wrong, it adds bytes.

Here is a response using 127: (the first line is the value out, the second line is the response back)

[0, 0, 0, 127]
[32, 0, 0, 0, 127]: 127

Now with 128:

[0, 0, 0, -128]
[32, 0, 0, 0, -17, -65, -67]: 239

I am at a loss and am not sure what I am doing wrong. I think it is an encoding issue involving signed / unsigned numbers but am not sure, especially since bytes are being added in from the response. I have successfully retrieved data using a responseStreamReader for String data but my data is getting more complicated and includes characters that split the String causing issues. Below is my code:

First for the PHP, very simple retrieve-respond:

<?
$data = file_get_contents('php://input');
echo $data;
?>

and now for my java code:

public static void makeConnection(String urlPath, ByteArrayOutputStream outStream, ByteArrayOutputStream inStream) throws IOException {
    HttpURLConnection con = null;
    URL url = new URL(urlPath);
    con = (HttpURLConnection) url.openConnection();
    con.setUseCaches(false);
    con.setDoOutput(true);

    con.setRequestMethod("POST");
    con.setRequestProperty("Connection", "Keep-Alive");
    con.setRequestProperty("Cache-Control", "no-cache");
    con.setRequestProperty("Content-Type", "Content-Type: application/octet-stream");
    
    DataOutputStream request = new DataOutputStream(con.getOutputStream());
            
    System.out.println(Arrays.toString(outStream.toByteArray()));   //what the byte array looks like going out
    
    request.write(outStream.toByteArray());

    request.flush();
    request.close();
    
    DataInputStream resp = new DataInputStream(con.getInputStream());
    DataOutputStream rosp = new DataOutputStream(inStream);
        
    byte[] b = new byte[1024];
    int len;
    while((len = resp.read(b, 0, 1024)) > 0){
        rosp.write(b, 0, len);
    }
    
    rosp.close();
    resp.close();
    
    con.disconnect();
}
public static void main(String args[]) {
    try {
        ByteArrayOutputStream bs = new ByteArrayOutputStream();
        DataOutputStream request = new DataOutputStream(bs);            
        
        ByteArrayOutputStream is = new ByteArrayOutputStream();
        
        request.writeInt(128);      //127 works, this does not
        
        makeConnection(urlWip, bs, is);
        
        byte resp[] = new byte[is.size()];
        resp = is.toByteArray();    
    
        request.flush();
        request.close();
        
        bs.flush();
        bs.close();

        is.flush();
        is.close();
        
        ByteArrayInputStream bis = new ByteArrayInputStream(resp);
        DataInputStream response = new DataInputStream(bis);    
        
        response.readByte();                //There is a space padding response. Why?
        int test = response.readInt();      //Here is where our response should be
        
        response.close();
        bis.close();
        
        System.out.println(Arrays.toString(resp) + ": " + test);
        
    } catch (MalformedURLException | SocketException e) {
        System.out.println("url error");                            // Connection Error. Check Internet and Try Again
    } catch (IOException e) {   
        System.out.println("data error");                       //Corrupted File Error  
    }
}
Jaypal Sodha
  • 2,238
  • 2
  • 10
  • 22
Zero
  • 67
  • 10
  • In Java, byte data type is an 8-bit signed two's complement integer. Normally it has a minimum value of -128 and a maximum value of 127 (inclusive) – Ken Lee Jun 03 '21 at 04:19
  • I know that about java. But why is it that when I send out the data, it comes back differently? if I send out a integer with the binary values [0, 0, 0, -128] why does it not come back that same way from php? Instead it comes back as [0, 0, 0, -17, -65, -67] which not only is not correct, but adds two bytes. – Zero Jun 03 '21 at 04:37
  • the php just returns what you input (you are using 'php://input'). So it is the input to the PHP (i.e. the output from java) which is causing this. – Ken Lee Jun 03 '21 at 04:45
  • The data inside of the ByteArrayOutputStream is [0, 0, 0, -128] right before being passed into the DataOutputStream. Is the DataOutputStream or the HttpURLConnection changing or adding extra data before it is sent out to the php page then? – Zero Jun 03 '21 at 04:52
  • Yes you are right because once there is overflow in data , you cannot predict what the system will be doing. (it depends on the system hardware and software architecture) – Ken Lee Jun 03 '21 at 05:07
  • The problem with that is that I am passing 128 in as an int: request.writeInt(128);. 128 falls between -2^31 to 2^31-1, so it should not be an overflow error. Additionally that still does not explain where the stray 32 (or space character) is coming from that is being appended to the front of the response. Doing more testing, the php page does receive the 128 when the bytes are re-combined and saved to a file on the server. Now for the strange behavior. Directly echoing back something like echo chr(-16); gives that same wrong array response. Anything that is not between 0 and 127 does. – Zero Jun 04 '21 at 04:20
  • You are using toByteArray() in your makeConnection function. For integer you may use something like IntToByteArray [IntToByteArray](https://stackoverflow.com/questions/2183240/java-integer-to-byte-array). – Ken Lee Jun 04 '21 at 04:57
  • That example doesn't answer my question. Firstly, they are storing the int into a byte array (because fundamentally all types are byte arrays anyways - an int being an array of 4 bytes) which you suggested against. Secondly, that answer does not explain how to output the data into a stream. And finally, when you do get further down, they are using ByteArrayOutputStream which is what I am using. The data is sent out properly, server side I can even see that the array converts to 128. But upon echoing the data back something happens, either at server echo or when my program receives the data. – Zero Jun 06 '21 at 03:23

1 Answers1

0

I finally figured out the solution. The issue was how the PHP page was receiving the data. This was not an issue with my java code or how the data was being sent but instead how PHP was perceiving it and echoing it back. Setting the header just below the <?php tag fixes it:

header('Content-Type:application/json; charset=utf-8');

I still have the issue with a space being appended to the front of the stream, but simply calling response.readByte(); removes it.

The following pages helped with the first actually having the answer that I needed:

UTF-8 content Java request and PHP response

echo char(128) and above from php does not work

Zero
  • 67
  • 10