I'm stuck with interpreting a response from a C server to my java application. Hoping that the C server is responding to my java in BIG_ENDIAN format, my question is how would I convert the response to an Integer. I'm pasting the response I got from the the C server and wondering how would I do "be64toh" function in java.
Response from the C server -
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^H^#^#^#^#^#^A^A^B^#^#^#^N^#^#^#^#^#^#^#^#^#^#^#^H^#^#^#^#^#^#^#^A^#^#^#^K^#^#^#^#^#^#^#^#^#^#^#<80>^#^#^#^#^#^#^BÃ^#^#^#^AYour
request is successfully registered with us and is under
processing.^#^#^#^#^D^#^#^#^#^#^#^#¨ýf^#^#^#^#^#mX#^#^#^#^#^#^#^#^#^N^#^#^#^#^#^#^#^#^#^#^#^H
I'm not sure how to interpret the non readable bytes and when converted to hexadecimal most of them are null but few of them are filled with data just like the ^H, ^A etc.. Can you please help me find a solution for this one.
Suppose you have a java.nio.SocketChannel to read from, you can use a ByteBuffer to do the conversion:
private static final int BUFFER_SIZE = 1024;
ByteBuffer readBuffer = ByteBuffer.allocate(BUFFER_SIZE).order(ByteOrder.BIG_ENDIAN);
int bytesRead = socketChannel.read(readBuffer);
readBuffer.flip();
Now you can read your data out of the buffer, e.g.:
int someInt = readBuffer.getInt();
long someLong = readBuffer.getLong();
Related
I am trying to interface a Nextion HMI Serial Screen to Android Things, specifically the PICO-PI-IMX6UL
I am using the sample-uartloopback template as a starting place.
What I need to do is send the following payload over serial (UART3) in a certain format and in ASCII
page 1
The instruction is ended with three bytes "0xff 0xff 0xff"
All the instructions and parameters are in ASCII
All the instructions are in lowercase letters
mLoopbackDevice.write(buffer, buffer.length);
Where buffer is the payload with the three terminating bytes.
The thing is the screen wants in in ASCII but I can only send in the bytearray...
I have tried multiple ways and I cant seem to get it to work.
What would be the proper way to format a string of "page 1" and then add the terminating bytes?
I have it working in a node app but java is blowing my mind right now...
I have tried:
String strCommand = "page 1";
byte b = (byte)0xFF;
byte[] endCommand = {b,b,b};
byte[] cmd = strCommand.getBytes();
ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
outputStream.write(cmd);
outputStream.write(endCommand);
byte[] payload = outputStream.toByteArray();
Screen.write(payload, payload.length);
but that does not work.
I can read data (nothing useful at the moment) so I can confirm the communication is fine and It works in my Node app, but I need to port it to Android Things...
Can anyone point me in the right direction?
EDIT: This returns the correct format for me in JS
function hex(str) {
var arr = [];
for (var i = 0, l = str.length; i < l; i ++) {
var ascii = str.charCodeAt(i);
arr.push(ascii);
}
arr.push(255);
arr.push(255);
arr.push(255);
return new Buffer(arr);
}
I'm trying to send a string through netty with a ByteBuf.
First of all I convert the string to a byte array like that:
byteBuf.writeInt(this.serverName.length());
byteBuf.writeInt(this.ipAdress.length());
byteBuf.writeBytes(this.serverName.getBytes(StandardCharsets.UTF_8));
byteBuf.writeBytes(this.ipAdress.getBytes(StandardCharsets.UTF_8));
This works well, but I don't know how to read the bytes to convert them back to the string?
I tried something like that:
int snLen = byteBuf.readInt();
int ipLen = byteBuf.readInt();
byte[] bytes = new byte[byteBuf.readableBytes()];
System.out.println(byteBuf.readBytes(bytes).readByte());
this.ipAdress = "";
There must be something to get the bytes back. You can send bytes from a string but can't get the bytes back at the end? Seems like there is a method for that, but I don't have an idea how to do that.
I hope anyone from you can help me.
Thanks in advance! :)
In netty 4.1 you can use:
byteBuf.writeCharSequence(...)
byteBuf.readCharSequence(...)
How about using Netty's own StringEncoder and StringDecoder ? http://netty.io/4.1/api/io/netty/handler/codec/string/StringEncoder.html
Here is an untested answer:
I assume the data order is correct.
Use this, method "readBytes(ByteBuf dst, int length)" : readBytes
Transmit side change to:
byteBuf.writeInt(this.serverName.getBytes().length);
byteBuf.writeInt(this.ipAdress.getBytes().length);
Receiving side:
int snLen = byteBuf.readInt();
int ipLen = byteBuf.readInt();
byte[] bytesServerName = new byte[snLen];
byte[] bytesIp = new byte[ipLen];
byteBuf.readBytes(bytesServerName,snLen);
byteBuf.readBytes(bytesIp, ipLen);
String serverName = new String(bytesServerName);
String ipAddress = new String(bytesIp);
System.out.println(bytesServerName);
System.out.println(bytesIp);
I have got a Java Server and a C# Client. And I'm really certain something goes wrong with the outputstreamer on the client or inputstream on the server.
byte[] arr = IOUtils.toByteArray(is,14);
PrintWriter out = new PrintWriter(os, true);
out.print("Received "+ new String(arr,"UTF-8"));
out.flush();
out.close();
"is" in this case is the Input Stream Variable. Coming from Socket.getInputStream().
Removing the length of the stream (14 in this case) makes the system time-out. The client does not get any respons except: "Read Failure"
The client side consists of a C# program
byte[] start = getIdentifier();
byte[] end = Encoding.UTF8.GetBytes(toSend);
byte[] arr = start.Concat(end).ToArray();
//Arr variable is a couple of strings smashed together and transformed into a byte[]
networkStream.Write(arr, 0, arr.Length);
networkStream.Flush();
StreamReader streamReader = new StreamReader(networkStream);
result = streamReader.ReadToEnd();
I actually tried writing to the Server with a BinaryWriter too, but that didn't work either. If I know what the length of the data is that will be send, I can fix the problem. But I do not know how to send the length of the stream to the server.
I've tried using Available() to see how much there was to read, but for some reason that sometimes was 0. As if the data wasn't been sent by the client yet.
Any ideas of how to fix the freezing?
EDIT:
I think I understand how the streaming works now.
At first I did this on the client side:
var length = BitConverter.GetBytes(arr.Length);
Array.Reverse(length);
Then on the server side I put this piece of code:
/* Get Input Data Length */
byte[] arr = IOUtils.toByteArray(is, 4);
int length = (arr[0] << 24) & 0xff000000 |
(arr[1] << 16) & 0x00ff0000 |
(arr[2] << 8) & 0x0000ff00 |
(arr[3] << 0) & 0x000000ff;
/* Get Input Data */
arr = IOUtils.toByteArray(is, length);
#Andreas your mention of the big-endian byte order made it clear how to send the length to the server
in my Client-Server application I found a strange error. I got the following Methods :
sendLoginResponse();
sendPlayerList();
sendCurrentLevelState();
Each Methods sends a byte array to the Client-Side
If I only call 2 of them, everything works fine and the Client-Side gets all the sent byte arrays. But if I call all 3 of them only the first and second one arrive the Client, the order of the following methods doesnt matter. but the Server says all of them were send. To write to the Client iam using the
write(byte[] b, int off, int len); method
all The lenghts within the packages make sense too.
Here comes the strange point:
if I add a Thread.sleep(1000); after the second Method, the third one does now arrive the Client after the sleep. I Have also tried to flush the DataOutputStream after every write call, but this didnt help.
EDIT:
So let's say I'd send 3 Login-Response
The Method's that gives me the byte[]:
public byte[] getLoginResponse(int playerID){
byte[] msg = new byte[4];
short shortMsgLength = 4;
byte[] msgLength = shortToBytes(shortMsgLength);
msg[0] = 2;
msg[1] = msgLength[0];
msg[2] = msgLength[1];
msg[3] = (byte) playerID;
return msg;
}
private byte[] shortToBytes(short value) {
byte[] returnByteArray = new byte[2];
returnByteArray[0] = (byte) (value & 0xff);
returnByteArray[1] = (byte) ((value >>> 8) & 0xff);
return returnByteArray;
}
And the Send Method:
private void sendLoginResponse() {
try{
byte[] msg = rfcObject.getLoginResponse(playerID);
out.write(msg,0,msg.length);
}catch(Exception e){
System.err.println(e.getMessage());
System.exit(0);
}
}
So if I call the sendLoginResponse(); three times in a row, the client only recieves 2 byte-arrays, but the server says it has been sent 3 times. If i add a
Thread.sleep(1000); `after the second Method-Call, everything works fine..`
The Client that reads the message runs in a Thread:
public void run(){
while(true){
try {
byte[] data = new byte[MAX_DATA_SIZE]; // MAX_DATA = 255
byteCount = in.read(data);
} catch (IOException ex) {
handleExceptionError(ex);
}
}
}
thank you!
if I call the sendLoginResponse(); three times in a row, the client only recieves 2 byte-arrays, but the server says it has been sent 3 times.
This is because TCP is a stream-oriented protocol. Meaning it doesn't know or care how your messages are delimited. There's no concept of individual messages in TCP, just a stream of bytes, with the guarantee that the order of bytes is preserved.
So when the sender calls three write, the three byte arrays are simply concatenated over the connection and arrives at the receiver in the same order, but the receiver doesn't necessarily need three read to get all the bytes, and even if it does take three read, the read doesn't necessarily gives you the same byte array passed to each corresponding write.
Your message already have the necessary information to get the individual message back from the byte stream:
// Client code for reading individual messages from a TCP connection
byte type = din.readByte();
// Read the message length, little-endian.
// We cannot use din.readShort because it's big-endian
int lenLo = din.read();
int lenHi = din.read();
short len = (short)(lenLo | (lenHi << 8));
byte [] body = new byte[len];
din.readFully(body);
DataOutputStream and TCP don't lose data.
As almost invariable seen in questions of this nature, the problem is at the receiving end. You are probably assuming that `read()' fills the buffer, and ignoring the count that it returns.
Based on your protocol description in comments, you should be using DataInputStream.readFully() in this circumstance:
byte type = din,readByte();
int length = din.readShort();
byte[] data = new byte[length];
din.readFully(data);
I am making a chat program in which I have to separate a file into 1024 Bytes chunk and send it over Socket in this format:
<DataPacket>Binary_data<DataPacket\>
Currently, my only idea is to send a string
"<Packet>"
then a Byte[1024] and then a string
"<Packet\>".
So my question is:
Is there a more convenience way to do this?
Which Java class for input/output (DataInputStream, BufferedOutputStream,... ) is most suitable and a small example code of doing this?
Additional Info:
I must use Java library (JRE8), no Apache,...
I understand that I dont have to separate the data in TCP, it just be a must.
It would be very good if all the code can be run from a function like:
void SendFile(Socket sendingSocket, File fileToSend);
void ReceiveFile(Socket receivingSocket);
To chunk binary data, it's usually better to send the number of bytes first and then the raw data as bytes. So your chat client should send the string "Packet 711\n" first, then 711 bytes of the file (most file sizes are not multiples of 1024!).
That way, you can send the data in chunks and make the last chunk as small as necessary in order to avoid to corrupt the file. The line feed after the size makes it easier for the recipient to determine where the number ends and where the real raw data starts.
[EDIT] If you can't change the protocol much, maybe this works: <DataPacket>711\n ... 711 bytes binary data ... </DataPacket>
So the code to send the data would look like this:
void SendFile(Socket sendingSocket, File fileToSend) {
OutputStream stream = sendingSocket.getOutputStream();
InputStream input = new FileInputStream(fileToSend);
byte[] buffer = new byte[1024];
int len;
while(true) {
len = input.read(buffer);
if(len < 0) break;
String header = "<DataPacket>" + len + "\n";
stream.write(header.getBytes('ASCII'));
stream.write(buffer, 0, len);
String footer = "<DataPacket\>";
stream.write(footer.getBytes('ASCII'));
}
input.close();
stream.close();
}
On the receiving side, you need to parse the header (which includes the number of bytes to expect). Then you can allocate a buffer and read the bytes.