Creating a packet bytearray using a bytebuffer in Java - java

How can I make a packet that is in the form of a byte[] in Java? I know that it should be done with a ByteBuffer and then I need to make it a byte[] and send it through a DataOutputStream.

How can I make a packet that is in the form of a byte[] in Java? I know that it should be done with a ByteBuffer and then I need to make it a byte[] and send it through a DataOutputStream.
No, you don't know that. You either:
Use a ByteBuffer and send it through a Channel directly, without an intermediate byte[]
Use a DataOutputStream wrapped around a file or socket output stream, again without an intermediate byte[]
use a DataOutputStream wrapped around a ByteArrayOutputStream, get the byte[] array from that, and send the byte[] array. This technique is unnecessary unless what you're trying to construct is a DatagramPacket.

Related

Read and write to TCP socket in Java

I am creating a simple TCP server in java which accepts clients. Each client that connects to the server sends a message, and sends an answer based on the message.
In order to accept clients I am using ServerSocket class. In order to read the client's message and write to him I am allowed to use only in the Socket, DataOutputStream and DataInputStream classes and in StandardCharsets.UTF_8. In addition, every message that the server gets and sends must be in UTF-8 encoding.
However, I am not sure how to read and write messages in UTF-8 encoding using those classes. The size of the messages is unbounded. I tried to read about the read function of DataInputStream class, but I couldn't understand how to use it (if this indeed the function I need to use).
DataOutputStream has a writeUTF() method, and DataInputStream has a readUTF() method. Just note that these methods deal in modified UTF-8 rather than standard UTF-8, and they limit the UTF-8 data to 65535 bytes max.
To provide interoperability with non-Java clients, and/or handle longer strings, would be better to just handle the UTF-8 yourself manually.
The sender can use String.getBytes() to encode a String to a byte[] array using StandardCharsets.UTF_8, then send the array's length using DataOutputStream.writeInt(), and then finally send the actual bytes using DataOutputStream.write(byte[]).
The receiver can then read the array length using DataInputStream.readInt(), then allocate a byte[] array and read it using DataInputStream.readFully(), and then finally use the String constructor to decode the bytes using StandardCharsets.UTF_8.

Is it possible to add several strings and a bitmap to a ByteArrayOutputStream

I'm writing several strings to a ByteArrayOutputStream using a DataOutputStream as follows:
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
DataOutputStream dataStream = new DataOutputStream(byteStream);
dataStream.writeUTF(string1);
etc.
However I would also like to add a Bitmap to the ByteArrayOutputStream.
Is it possible to first write the strings using the DataOutputStream and then write the bitmap directly to the ByteArrayOutputStream using write()?
How would it be possible to know the number of bytes to read when unstreaming it after writing it?
Or is it possible to pass the ByteArrayOutputStream to Bitmap.compress() after the string have been written?
I have no idea why you trying to do this but well...
After you write string to dataStream, do flush on dataStream and you will be sure, that stream is ready to eat more data. Next you can write bitmap to byteStream. Do not forget to flush and close streams. All operations should be done in try block. After you write String to dataStream you can take current offset by size() method.

Cannot read in Java data serialized in C++

I have a Java client connected via socket to a C++ server.
The C++ server sends back to the client serialized objects.
However serialization works differently for Java and C++, so I cannot read the objects in that way:
objectInputStream.readObject();
This forces me to read each single value of the object manually:
byte[] buffer = read(FOUR_BYTES);
int flag = convertBufferToInt(buffer);
byte[] buffer = read(FOUR_BYTES);
float price = convertBufferToFloat(buffer);
// More stuff
myObject.setFlag(flag);
myObject.setPrice(price);
// More stuff
That's very hard to maintain. Isn't there an easier way to fill in my object with data?
To solve this in general you would need to write a C++ parser for objects serialized in Java. This is no small task.
Rather, I would recommend that you find some serialization format that is easy to parse and share between your Java and C++ programs. Preferably a format where there exists Java as well as C++ libraries for the serialization/deserialization. JSON or Google Protocol Buffers are obvious candidates.
Yes there is (are). You have 2 options using only the standard library:
Using the DataInputStream class
Check out the DataInputStream class. It has methods to read values of primitive types like readByte(), readInt(), readLong(), readFloat(), readChar(), readUTF() (for reading UTF-8 encoded String) etc.
So your code becomes as simple as:
// Obtain InputStream from Socket:
InputStream is = ...;
// Create DataInputStream:
DataInputStream dis = new DataInputStream(is);
myObject.setFlag(dis.readInt());
myObject.setPrice(dis.readFloat());
Using the ByteBuffer class
For this you have to read first the whole data into a byte array. Once you've done that, you can create a ByteBuffer using the ByteBuffer.wrap(byte[] array) method. The ByteBuffer class also supports reading primitive types just like the DataInputStream class.
The good thing about ByteBuffer that it supports changing the byte order (the order how the low and high bytes of a multi-byte value like int are read/written): ByteBuffer.order(ByteOrder bo). This is very useful if you're communicating with systems which use a differnet byte order (which might apply in your case).
Example using ByteBuffer:
// Read all your input data:
byte[] data = ...;
// Create ByteBuffer:
ByteBuffer bb = ByteBuffer.wrap(data);
myObject.setFlag(bb.getInt());
myObject.setPrice(bb.getFloat());

Java and Binary data in the context of sockets

Java newbie here. Are there any helper functions to serialize data in and out of byte arrays? I am writing a Java package that implements a network protocol. So I have to write some typical variables like a version (1byte), sequence Number (long) and binary data (bytes) in a loop. How do I do this in Java? Coming from C I am thinking of creating a byte array of the required size and then since there is no memcpy() I am converting the long into a temporary byte array and then copying it into the actual byte array. It seems so inefficient and also really error prone. Is there a class I could use to marshall and unmarshall parameters to a byte array?
Also why does all the Socket classes only deals with char[] and not byte[]? A socket by definition has to deal with binary data also. How is this done in Java?
I am sure what I am missing is the Java mindset. Appreciate it if some one can point it to me.
EDIT: I did look at DataOutputStream and DataInputStream but I cannot convert the bytes to a String not to a byte[] which means the information might be lost in the conversion to write to a socket.
Pav
Have a look at DataInputStream, DataOutputStream, ObjectInputStream and ObjectOutputStream. Check first if the layout of the data is acceptable to you. Also, Serialization.
Sockets neither deal with char[] nor with byte[] but with InputStream and OutputStream which are used to read and write bytes.
If you are sending the data over a socket, then you don't need a temporary byte array at all; you can wrap the socket's OutputStream with DataOutputStream or ObjectOutputStream and just write what you want to write.
There might be an aspect I've missed that means you do actually need temporary byte arrays. If so, look at ByteArrayOutputStream. Also, there's no memcpy(), sure, but there is System.arraycopy.
As above, DataInputStream and DataOutputStream are exactly what you are looking for. Re your comment about String, if you're planning to use Java Strings over the wire, you're not designing a network protocol, youre designing a Java protocol. There are readUTF() and writeUTF() if you're sure the other end is Java or if you can code the other end to understand these formats. Or you can send as bytes along with the appropriate charset, or predefine the charset for the entire protocol if that makes sense.

How to get number of bytes?

How do I obtain the number of bytes before allocating the byte size of the array 'handsize' as shown below as the incoming ByteArray data are sent in 3 different sizes. Thanks.
BufferedInputStream bais = new
BufferedInputStream(requestSocket.getInputStream());
DataInputStream datainput = new DataInputStream(bais);
//need to read the number of bytes here before proceeding.
byte[] handsize = new byte[bytesize];
datainput.readFully(handsize);
You could use a ByteArrayOutputStream, then you wouldn't have to worry about it.
ByteArrayOutputStream out = new ByteArrayOutputStream();
//write data to output stream
byte[] bytes = out.toByteArray();
There's no way to know how many bytes of data are yet to be received on a socket--knowing this would be tantamount to clairvoyance. If you're using your own protocol for client/server communication, you could send the number of bytes of data as an integer, before sending the actual bytes themselves. Then the receiving side would know how many bytes to expect.
As has been pointed out, the problem as stated is impossible. But why do you need to know? Why not store the data in a variable size structure, like an ArrayList, as you read it? Or maybe even process it as you read?

Categories