receiving a C struct from serial port using Java - java

I've got two programs. one is written in C, sending out structs of unsinged chars via serial port.
The other one is written in Java and supposed to receive this data.
I'm using the jSSC library which returns a byte array after reading from the serial port.
How can I now extract the original values?
what is send: 1,99,23,15,16,17,18
bytes I received: [B#c1c428
bytes converted to chars: [C#13526b0
Sending the data works correctly. I also wrote a C program to read the data which receives it correctly so the problem seems to be in the Java program.
System.out.println("Port " + PortName + " opened: " + serialPort.openPort());
//serialPort.setParams(9600, 8, 1, 0);
byte[] input;
if((input = serialPort.readBytes()) == null){
System.out.println("No data to be read");
System.exit(0);
}
char[] chars = new String(input).toCharArray();
System.out.println("Bytes read: " + input.length);
System.out.println("Byteoutput: " + input);
System.out.println("Charoutput: " + chars);

In order to actually output a byte array you need to do something like:
System.out.print("Byte output: ");
for(int i=0; i < input.length; ++i)
System.out.print(((int)input[i]) + ", ");
System.out.println();

Related

Why is extra data being written to my output stream and how can I stop this?

I am trying to build a simple connection between my Java server (it sends information) and my C client (it receives info).
I want to send one single integer representing the size of an array and then a byte array itself. My java code looks like this
Socket sc = new Socket("52.187.54.73", 19000);
while(true)
{
System.out.println("Socket open");
DataOutputStream outToClient = new DataOutputStream(sc.getOutputStream());
Random rand = new Random();
int rlen = rand.nextInt(10)%10 + 1;
byte[] a = new byte[rlen];
System.out.println("Size of the array is " + rlen);
for(int i = 0; i < rlen; i++)
a[i] = (byte)rand.nextInt(100);
outToClient.write(rlen);
outToClient.write(a,0,rlen);
//close socket
sc.close();
System.out.println("Done!");
//Break once done
break;
}
and my C code looks like this
ptr1 = (void *)calloc(1, sizeof(int));
while(1){
sin_size = sizeof(client_addr);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size);
printf("\n Got a connection from (%s ,%d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
bytes_received = recv(connected,ptr1,10,0);
if(bytes_received<0){
printf("Something went wrong %s\n", strerror(errno));
}
printf("Bytes received: %d \n", bytes_received);
for(int i =0; i<bytes_received; i++){
unsigned char a = *(unsigned char *)(ptr1 + i*sizeof(unsigned char));
printf("Inc: %d", a);
}
Assuming that the above block of code works and I am able to get the value of rlen the code for processing the array is as follows:
ptr2 = calloc(rlen, sizeof(unsigned char));
bytes_received = recv(connected, ptr2, 1,0);// incoming, 0);
printf("bytes received: %d\n", bytes_received);
for(int i = 0; i < rlen; i++){
printf(" i = %d, val = %d\n ", i,*(unsigned char *)(ptr2 + i*sizeof(unsigned char)));
}
Now the Java server sends a number between 1 and 10. I was earlier trying to read the number sent using int incoming = *(int *)ptr1; but for some reason, occasionally I would get huge values like 51020210.
To check why this was happening and debug I wrote the code block:
for(int i =0; i<bytes_received; i++){
unsigned char a = *(unsigned char *)(ptr1 + i*sizeof(unsigned char));
printf("Inc: %d", a);
}
It turns out that sometimes, the integer being sent becomes very large.
Why is this happening? On the server side printing out rlen shows me the right value, but non-deterministically I get random really large values at the client side.
Note that whatever number I receive on the client side has the first number as the value of rlen.
So for example if rlen is 6, then the random really large value is something like 689932423
Later the values of rlen will become very large in the order of 1000s so I need to solve this problem and cannot simply take the first byte of whatever I get on the client side.
The problem with my code was in this line as rightly pointed out in the comments
bytes_received = recv(connected,ptr1,10,0);
I was mistakenly trying to read more than 4 bytes which is the exact number needed to convert to an integer value.
Alternatively, to read 4 and only 4 bytes, this could be written as
bytes_received = recv(connected, ptr1, 4, 0|MSG_WAITALL);
On the java side, again as pointed out in the comments, the function write(int) only sends 1 byte.
To send multiple bytes first the integer must be converted into a 4 byte array, and then each byte in the array must be sent like this
outToClient.write(rlen_array, 0, 4);

ObjectOutputStream.writeBytes(String s) unexpected output values

I am using an ObjectOutputStream object os to send a String msg from a client Android app to a c++ server.
I know how my msg must be received by the server:
each char of the msg is stored in a byte array (received_msg[]). I also know the exact msg the server expects (through another c++ app).
The data I send is a string made from 1 byte array and 2 other string.
My problem:
I already used PrintWriter to send my data, but my server would always display some weird char in received_msg, at index 24 to 28.
I tried a lot of conversions to fix it, but gave up on that.
So I tried sending msg with ObjectOutputStream.
With the client using ObjectOutputStream.writeBytes(), the server shows almost the right received message. Almost because there are characters that are added at the beginning.
Something like that :
In the server received_msg:
index 0: ┐
index 1: i
index 2: ''
index 3: |
index 4: I //beginning of the message I actually wanted to send
index 5: S //every char following index 4 is good.
while I expected and sent nothing before 'I''S'.
The message I send begins like that : ISOXXXXX
So I was wondering if there were any ways to retrieve the REAL output of ObjectOutputStream.writeBytes. I know that it's Output, not Input, still that would help me understand how it adds the weird header.
Thanks in advance for your suggestion
My send function
private void send(String o) {
System.out.println("socket");
try {
this.socket = new Socket(serverIP, portNumber);
os = new ObjectOutputStream(socket.getOutputStream());
//OutputStreamWriter out = new OutputStreamWriter(socket.getOutputStream());
//InputStreamReader in = new InputStreamReader(socket.getInputStream());
// PrintWriter pw = new PrintWriter(out, true);
System.out.println("Connected to server : " + this.socket.getInetAddress() + " on port " + this.socket.getPort());
System.out.println("from local address: " + this.socket.getLocalAddress() + " and port: " + this.socket.getLocalPort());
System.out.println("02. -> Sending an object...");
ArrayList<String> tempoStr = StringToByteArray(o);
String msg="";
for(String inStr :tempoStr)
msg+=inStr;
System.out.println("the message I ACTUALLY send is\n"+msg); //the result in console is EXACTLY the message I expect.
os.writeBytes(msg); //then when I check on the server: unexpected additionnal chars at the beginning.
os.flush();
// pw.write(msg);
//pw.flush();
System.out.println("send success");
} catch (IOException e) {
e.printStackTrace();
System.out.println("XX. Exception Occurred on Sending:" + e.toString() +"\n"+ e.getCause());
System.out.println("Socket creation failure or error on sending.");
}
}
PS: I cannot change the server code.
Do not use ObjectOutputStream (java only). One might use DataOutputStream, but here it seems you want something simple.
byte[] a = ...
String b = ...
OutputStream out = ...
out.write(a);
out.write((b + '\u0000').getBytes("UTF-8")); // Or "Windows-1252" / "ISO-8859-1"
out.flush();
I have added a '\0' as that is used in C/C++ to terminate strings (binary output).
Or maybe "\r\n" might be expected (text output).
The encoding is given explicitly.

Converting pointer to string and send as char array not working properly

I have a problem with sending directory names over socket from my C++ client, to my Java server.
Sending ordinary messages like "hello world", works great , but the following doesn't and I can not figure out what the problem is:
char const * files = ffd.cFileName; // get directory name
string str(files, 0, strlen(files)); // convert pointer to string, right?
char mess[str.size()];
strcpy(mess, str.c_str()); // make char array :)
cout << "Send file: " << mess << " with strlen: " << strlen(mess) << " and sizeof: " << sizeof(mess) << endl;
int sent = 0;
if ((sent = send(connectSocket, mess, sizeof(mess), 0)) == SOCKET_ERROR)
{
closesocket(connectSocket);
WSACleanup();
connectToServer();
}
The java server just receives the directory names like this:
wam
p
Win
dow
s
Win
dow
s.o
ld
wxW
idg
ets
I can not understand what I'm missing because I have tried every possible way to do this and the C++ client prints like:
"Send file: windows with strlen: 7 and sizeof: 7"
I do not think that the java server is the problem since I can receive normal strings and messages perfectly, but anyway here is the JAVA code:
is = socket.getInputStream();
byteArray = new byteArray[1024];
while (true) {
c = is.read(byteArray, 0, byteArray.length);
String recv = new String(byteArray, 0, c);
System.out.println(recv);
if (recv.equals("<EOF>")){
break;
}
list.add(recv);
}
If you request something else or anything just leave a comment and I will fix it.
Question: are you sending via TCP or UDP? I'm guessing TCP, and if that is the case, you need to treat the socket as more of a stream. That stream may get broken up into a bunch of packets - you don't really control that. What I might do is to prefix the string length of each directory (ex, 3foo, 4barz, etc), read from the socket and determine what constitutes as a logical block or string, and then assemble / print the strings based on that. If you go with that route, you need to track how much you read each time until you think you are done.
I solved it, Just added byteArray = new byte[1024]; and now it works:
while (true) {
byteArray = new byte[1024]; // I ADDED THIS AND NOW THE JAVA SERVER RECEIVES IT CORRECTLY!
c = is.read(byteArray, 0, byteArray.length);
recv = new String(byteArray, 0, c);
System.out.println(recv);
if (recv.equals("<EOF>")){
break;
}
list.add(recv);
}

BGS5T RS232 communication with 1-wire sensor

I have Gemalto BGS5T java module and 1-wire temperature sensor. I have java midlet which uses RS232 port to communicate with temperature sensor. But the problem is that, I get no response from the sensor no matter what I send. Sensor has the right voltage on it, so the connection should be fine.
I tried testing my program so that I connected rs232 port to computer and watched with terminal(Termite) if the sent data was correct and everything looks like it should.
Another test was that I connected temperature sensor directly to computer and sent data with terminal and it worked like it should. I even got responses on some random inputs like 9999. I checked the parameters for connection inside the terminal and copied them to java midlet, but with no success.
There was only one time that I got some responses, but when I tryed the next day to continue with the work I had no success.
Parameters inside terminal:
Baud rate:9600
Data bits : 8
Stop bits: 1
Parity: none
Flow control:RTS/CTS
Here is the Java code:
String strCOM = "comm:COM0;blocking=on;baudrate=9600";
commConn = (CommConnection)Connector.open(strCOM);
System.out.println("CommConnection(" + strCOM + ") opened");
System.out.println("Real baud rate: " + commConn.getBaudRate());
inStream = commConn.openInputStream();
outStream = commConn.openOutputStream();
System.out.println("InputStream and OutputStream opened");
while(1==1)
{
byte bC1 = (byte)Integer.parseInt("11000001",2);
byte C1 = hexToBin("C1");
byte bparameter2 = (byte)Integer.parseInt("00010111",2);
byte bparameter3 = (byte)Integer.parseInt("01000101",2);
byte bparameter4 = (byte)Integer.parseInt("01011011",2);
byte bparameter5 = (byte)Integer.parseInt("00001111",2);
byte bparameter6 = (byte)Integer.parseInt("10010101",2);
byte[] bArray = {bparameter2,bparameter3,bparameter4,bparameter5,bparameter6};
int ch;
try {
outStream.write(bC1);
Thread.sleep(50);
//outStream.write(bArray);
outStream.write(bparameter2);
outStream.write(bparameter3);
outStream.write(bparameter4);
outStream.write(bparameter5);
outStream.write(bparameter6);
System.err.println("inStream bytes:" + inStream.available());
if(inStream.available() > 0)
{
String msg = "";
while(inStream.available() > 0)
{
ch = inStream.read();
msg = msg + (char) ch;
}
System.out.println("Serial msg: " + msg);
}
outStream.write('9');
outStream.write('9');
outStream.write('9');
outStream.write('9');
Thread.sleep(100);
outStream.write('9');
outStream.write('9');
outStream.write('9');
outStream.write('9');
System.err.println("inStream bytes:" + inStream.available());
if(inStream.available() > 0)
{
String msg = "";
while(inStream.available() > 0)
{
ch = inStream.read();
msg = msg + (char) ch;
}
System.out.println("Serial msg: " + msg);
}
I had to use null modem cable to get it working.

Java String to array of bytes wrong conversion

I have a client server Java code and the client is reading in a string "input" and it should then decrypt it, the decryption function needs an array of bytes, so I need to convert the string to array of bytes, which is done using "getBytes()" function, however it seems that this function is modifying the String! How can I convert the string into an array of bytes without changing its content.
String input = inputline.substring(66, inputline.length());
System.out.println("Read message +"+input+"+");
byte[] bx = input.getBytes(Charset.forName("UTF-8"));
System.out.println("Read message +"+bx.toString()+"+");
System.out.println("Read message +"+bx+"+");
the output of the code snippet is as follows:
Read message +[B#161cd475+
Read message +[B#4e25154f+
Read message +[B#4e25154f+
Try writing a for loop to print out the results. I believe Java is spitting out a random memory value for your output.
(int i = 0; s <= bx.length;i++)
{
System.out.println("Read message +" + bx[i].toString() + "+");
System.out.println("Read message +" + bx + "+");
}
Not sure if my for loop is correct, but it may give you something to work with. I hope this helps.
This should work for you. I needed to make a String object from the byte array...
String inputline = "[B#161cd475";
String input = inputline.substring(0, inputline.length());
System.out.println("Read message +"+input+"+");
byte[] bx = input.getBytes();
// Convert to String object
String tmp = new String(bx);
// Print statements.
System.out.println("Read message +" + tmp + "+");

Categories

Resources