1

Below are the parameters to send via socket in 5 byte data:

Parameters : methodname(1 byte), payloadlength(2 byte), payload(2 byte)

methodName = 5
payload = 2151

i want to send above three data in only 5 byte. The final sending byte are 0500020867. how to get this final bytes ?

  int methodname = 5;
  int payload  = 2151;

  ByteBuffer b = ByteBuffer.allocate(4);
        b.putInt(payload);
        byte[] payloadData = b.array();
        int payloadlength = payloadData.length;

    byte[] result = new byte[5];
    result[0] = (byte) (methodname);
    result[1] = (byte) (payloadlength >> 8);
    result[2] = (byte) (payloadlength);
    result[3] = (byte) (payload >> 8);
    result[4] = (byte) (payload);
    for (int i = 0; i < 5; i++)
             System.out.printf("%x\n", result[i]);
    result: 5 0 4 8 67 
    //expected result: 05 00 02 08 67

Can anybody help me out. Any sort of help would be appreciable. Thanks, Akash

AkashG
  • 7,868
  • 3
  • 28
  • 43

3 Answers3

2

Java is already big Endian. There is no need to perform the conversion for Network Byte Order.

Here is an example program demonstrating this. This is mostly taken directly from this answer. As you can see from the output, the first two bytes are 0, so the MSB is stored first.

import java.util.*;
import java.nio.ByteBuffer;


public class Main{ 
    public static void main(String[] args) {
        ByteBuffer b = ByteBuffer.allocate(4);
        b.putInt(2151);
        byte[] result = b.array();
        for (int i = 0; i < 4; i++)
            System.out.printf("%x\n", result[i]);
    }
}

Output:

0
0
8
67

Update: Here is how we make the OP's updated question work.

import java.util.*;
import java.nio.ByteBuffer;


public class Main{ 

    public static byte[] getBytes(int input) {
        ByteBuffer b = ByteBuffer.allocate(4);
        b.putInt(input);
        return b.array();
    }
    public static void main(String[] args) {
        int methodname = 5;
        int payload  = 2151;

        byte[] payloadBytes = getBytes(payload);
        int payloadlength = 2; // We always assume this is 2.

        byte[] result = new byte[5];
        result[0] = (byte) (methodname);

        // The following two lines are the same always.
        result[1] = 0; 
        result[2] = (byte) (payloadlength);

        // Here we put in the payload, ignoring the first two Most Significant Bytes
        result[3] = payloadBytes[2];
        result[4] =  payloadBytes[3];
        for (int i = 0; i < 5; i++)
            System.out.printf("%x\n", result[i]);
    }
}
Community
  • 1
  • 1
merlin2011
  • 71,677
  • 44
  • 195
  • 329
  • I have to send request data in 2-byte format only, so please suggest what i have to do. – AkashG May 02 '14 at 06:17
  • @AkashG: Use `ByteBuffer.putShort` instead of `ByteBuffer.putInt`. – Codo May 02 '14 at 06:18
  • @merlin2011: It's not true that *Java is already big Endian*. The reason your solution works is that *ByteBuffer* has explicit support for byte order and is initially in Big Endian mode. – Codo May 02 '14 at 06:20
  • @AkashG, With the above code you can already send the individual bytes of an `int` one at a time. Are you trying to send one _short_ at a time? – merlin2011 May 02 '14 at 06:22
  • @Codo, See this question for JVM Big Endian: http://stackoverflow.com/questions/981549/javas-virtual-machines-endianness – merlin2011 May 02 '14 at 06:23
  • @Codo, You are of course correct that `ByteBuffer` can produce the bytes in either order, but that point is orthogonal to my statement of the JVM's endianness. – merlin2011 May 02 '14 at 06:25
  • @merlin2011: Your reference shows what byte order is used in class files. It does not apply to how integers are stored in variables at run-time. If variables had to always be stored in big endian, then conversion of byte code into native code (as the JIT compiler does) would not work on Intel processors as they are unable to work in big endian mode. – Codo May 02 '14 at 06:28
  • Hi , Please check my below comments and suggest me. Three Parameters : methodname,payloadlength,payload where methodname = 5 and payload = 2151. now i want send above three data in only 5 byte. the final sending byte are 0500020867. how to get this final bytes ? – AkashG May 02 '14 at 06:29
  • 1
    @Codo, "Furthermore, the operand in an bytecode instruction is also big-endian if it spans multiple bytes." Are you suggesting that the variables are stored in little Endian in the JVM and the bytecode operands are big endian? – merlin2011 May 02 '14 at 06:30
  • @AkashG, Send a single `byte` containing `5`, then convert the payload to `byte[]` using the method in my answer, and send each byte. Now you have sent a total of 5 bytes. – merlin2011 May 02 '14 at 06:32
  • @merlin2011: It again refers to the class file. Let's say the byte code contains an instruction to add 500 to a variable. Then the constant 500 is the operand and will be encoded in big endian within the class file. It's part of the class loading to covert this to the native byte order. – Codo May 02 '14 at 06:37
  • 1
    @Codo, Your logic makes sense, but I would greatly appreciate some documentation describing the process of conversion of variables to native byte order during class loading, as well as the storage of variables in native byte order for the JVM. – merlin2011 May 02 '14 at 06:40
  • @merlin2011 i have edited my question & have tried with another way. Can u please suggest to get desired result. – AkashG May 02 '14 at 06:55
  • @AkashG, Are you assuming that the `int` is always small enough for 2 bytes? – merlin2011 May 02 '14 at 07:04
  • i have updated my question @merlin2011, can you please suggest whats wrong i am implementing as i am not able to read data from socket. – AkashG May 05 '14 at 06:41
  • @AkashG, It is time to ask a new question. If you keep changing the same question, it is unfair to the existing answers and confusing to the future readers. – merlin2011 May 05 '14 at 06:54
  • hello @merlin2011, i have asked another question as you said. Kindly refer this link - http://stackoverflow.com/questions/23466744/socket-giving-incorrect-response – AkashG May 05 '14 at 07:08
2

The ByteBuffer class that you are already using has methods for setting endianness, and putting/getting values of different lengths to the buffer. I suggest you use that.

Something like:

int methodname = 5;
int payload  = 2151;
int payloadLength = 2;

ByteBuffer buffer = ByteBuffer.allocate(3 + payloadLength); // 3 = for method name + length
buffer.order(ByteOrder.BIG_ENDIAN); // Just to be explicit

buffer.put((byte) methodname);
buffer.putShort((short) payloadLength);
buffer.putShort((short) payload);

buffer.rewind();
byte[] result = new byte[buffer.capacity()]; // Could also use result = buffer.array();
buffer.get(result);

for (int i = 0; i < result.length; i++) {
    System.out.printf("%02x ", result[i]);
}

Outputs:

05 00 02 08 67

As expected.


PS: The problem in your original code is:

ByteBuffer b = ByteBuffer.allocate(4);  // Here you allocate buffer of size 4
// ...
byte[] payloadData = b.array();         // The array will always have size of buffer
int payloadlength = payloadData.length; // ...meaning pD.length will always be 4
Harald K
  • 26,314
  • 7
  • 65
  • 111
1

Throw it all away and use DataOutputStream.writeInt(), or, as you want 2 bytes, writeShort().

NB your method SHORT_little_endian_TO_big_endian() is misnamed, because what it does has nothing to do with the endian-ness of the input, which has only to be in native order for the platform. It would work in C on both little-endian and big-endian hardware.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • i have edited my question & have tried with another way. Can u please suggest to get desired result. – AkashG May 02 '14 at 06:56
  • @AkashG I *have* suggested a way to get the desired result. If you want another way you need to say why, and what isn't satisfactory about this way. – user207421 May 02 '14 at 07:04