I have a Java app sending coordinates to a c# game in Unity. My data checks out with the exception of the negative values. I instead only get 63 or 250 something. Depending on the encoding.
Here is my Java client app:
#Override
public void run() {
//Keep in a loop as long as the running variable is true
while(running)
{
//Try catch block to catch exceptions for the networking code
try{
data1[0]=currentPlayer; // These are integers
.....
data1[8]=sendPause;
for(int i=0; i<=9;i++){
buf1[i]=(byte)data1[i]; //Casting to byte array
//System.out.println(buf1[i]);
}
//socket is created in "onCreate" earlier
socket.setTcpNoDelay(true);
out = socket.getOutputStream();
dos = new DataOutputStream(out);
dos.write(buf1, 0, buf1.length);
dos.flush();
synchronized(this){ this.wait(30); } //This is to minimize the frequency
}catch(Exception e)
{
Log.e("TCP", "Error",e);
}
}
}
This is my method for receiving in the C# server.
private void HandleClient(TcpClient client){
try{
byte[] bytes = new byte[256];
String data = null;
while(true)
{
data = null;
NetworkStream stream = client.GetStream();
int i;
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i);
byte[] msg = System.Text.Encoding.UTF8.GetBytes(data);
/*sbyte[] sbytes = new sbyte[msg.Length];
for (int j = 0; j < msg.Length; j++)
sbytes[j] = (sbyte)msg[j];
Debug.Log(sbytes[2]+" "+sbytes[3]);*/
packetID=msg[0];
switch(packetID){
case 1:
p1.joyLx = msg[1];
....
p1.pause = msg[8];
p1.active=true;
break;
....
case 4:
p4.joyLx = msg[1];
....
p4.active=true;
break;
}
}
client.Close();
}
}
catch(SocketException e)
{
Debug.Log("SocketException:"+e);
}
}
I've been looking into the whole signed/unsigned byte ordeal but I'm worried that upon saving it into a byte array beforehand is erasing this data.
P.S. this is my first visit here and I'm not really a programmer so I've probably missed something obvious. So sorry if I'm not accustomed...
Got it working! Thanks for the help and pointing out my oddities!
[...]byte[] bytes = new byte[256];
sbyte[] sbytes;
while(true)
{
NetworkStream stream = client.GetStream();
int i;
while((i = stream.Read(bytes, 0, bytes.Length))!=0)
{
sbytes = new sbyte[bytes.Length];
for (int j = 0; j < bytes.Length; j++)
sbytes[j] = (sbyte)bytes[j];
packetID=bytes[0]; [...]
I think your problem is that you are using a byte array in your C# code. A byte in java has a range of -128 to 127. A byte in C# ranges from 0 to 255. Try copying the received byte array into an sbyte array:
sbyte[] signedB = new sbyte[bytes.Length];
Buffer.BlockCopy(bytes, 0, signedB, 0, bytes.Length);
Check the values of signedB after this.
Related
I'm new with sockets and writing basic Java Client-to-Server-to-Client program that sends in this case
length of the message outToServer.writeInt(message.length); and byte[] message = new byte[10]; array to Server that reads and prints it to console and then modifies few bytes in the array and then sends it back to the Client. Client receives the array, reads it and and prints it to console.
My problem is that it prints only:
byte array received from server class:
0
0
0
0
0
0
0
0
0
0
[0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
when it should print some modified bytes with different numbers.
I assume there's some problem with for loop or in the reading part of the received bytes. Should i use readFully or something similar and how to do it correctly to loop the values i want?
Many thanks.
Client:
class TCPClient2 {
public static void main(String argv[])
{
try {
System.out.println("Client started");
Socket clientSocket = new Socket("localhost", 8080);
DataOutputStream outToServer = new DataOutputStream(clientSocket.getOutputStream());
System.out.println("\nByte array printed before sending to server:\n");
byte[] message = new byte[10];
//byte[] message = new byte[] { -1, -128, 1, 127, 23, 23, 23, 23, 23, 10 }; // you can try these too
message[0] = 1; // changes the first byte of the array
for(int i = 0; i < message.length; i++) {
System.out.println(message[i]); //prints byte array BEFORE being sent to server
}
System.out.println(Arrays.toString(message)); //prints byte array BEFORE being sent to server as String
System.out.println("\n");
outToServer.writeInt(message.length); // write length of the message
outToServer.write(message); // write the message
//
//
// Message -array is now sent to Server
//
// Waiting for answer
//
// Answer is now received from Server
System.out.println("byte array received from server class: \n");
DataInputStream inFromClient = new DataInputStream(clientSocket.getInputStream());
int length = inFromClient.readInt(); // read length of incoming message
/*
if(length>0) {
byte[] message = new byte[length];
dIn.readFully(message, 0, message.length); // read the message
}
*/
byte[] messageFromServer = new byte[length];
for(int i = 0; i < messageFromServer.length; i++) {
System.out.println(messageFromServer[i]);//prints received byte array
}
System.out.println(Arrays.toString(messageFromServer));//prints received byte array as a string
}catch (Exception e) {
e.printStackTrace();
}
}
}
Server:
class TCPServer2 {
public static void main(String argv[])
{
try
{
System.out.println("waiting for connections");
ServerSocket welcomeSocket = new ServerSocket(8080);
Socket connectionSocket = welcomeSocket.accept();
System.out.println("connection established");
DataInputStream inFromClient =
new DataInputStream(connectionSocket.getInputStream()); //receive byte array from client
int length = inFromClient.readInt(); // read length of incoming message
/*
if(length>0) {
byte[] message = new byte[length];
inFromClient.readFully(message, 0, message.length); // readFully the message, but how?
}
*/
byte[]message = new byte[length];
for(int i = 0; i < message.length; i++) {
System.out.println(message[i]); // print array
}
System.out.println(Arrays.toString(message)); // print array as string
System.out.println("message from client printed");
message[0]= 1; //change bytes of the received array
message[9]=1; //change bytes of the received array
DataOutputStream outToClient =
new DataOutputStream(connectionSocket.getOutputStream()); //send byte array with changes back to the client
outToClient.writeInt(message.length); // write length of the message
outToClient.write(message); // write the message
System.out.println("message to client sent");
} catch (Exception e) {
e.printStackTrace();
}
}
}
The problem is that you did not read the data from the socket, but only cycled through the local array.
You need to change these pieces of code:
1) Server
from:
byte[]message = new byte[length];
for(int i = 0; i < message.length; i++) {
System.out.println(message[i]); // print array
}
to:
byte[]message = new byte[length];
for(int i = 0; i < message.length; i++) {
message[i] = inFromClient.readByte();
System.out.println(message[i]); // print array
}
2) client
from:
byte[] messageFromServer = new byte[length];
for(int i = 0; i < messageFromServer.length; i++) {
System.out.println(messageFromServer[i]);//prints received byte array
}
to:
byte[] messageFromServer = new byte[length];
for(int i = 0; i < messageFromServer.length; i++) {
messageFromServer[i] = inFromClient.readByte();
System.out.println(messageFromServer[i]);//prints received byte array
}
An example is without specifying controls, the length of the array, ...
Or with your function readFully
1) Server
int length = inFromClient.readInt(); // read length of incoming message
byte[] message = new byte[length];
if (length > 0) {
inFromClient.readFully(message, 0, message.length); // readFully the message, but how?
}
for (int i = 0; i < message.length; i++) {
System.out.println(message[i]); // print array
}
2) Client
int length = inFromClient.readInt(); // read length of incoming message
byte[] messageFromServer = new byte[length];
if (length > 0) {
inFromClient.readFully(messageFromServer, 0, messageFromServer.length); // read the message
}
for (int i = 0; i < messageFromServer.length; i++) {
System.out.println(messageFromServer[i]);//prints received byte array
}
This question already has answers here:
Removing the first 16 bytes from a byte array
(4 answers)
Closed 3 years ago.
I have a byte array named byteArr[].I need to remove first 4 bytes from it.My code is shown below. Here I use the byte array to store the input string.I got some unwanted byte with the output i.e the first four bytes is not needed from the fifth onwards is correct. My program is to take id from respected rfid tag using an rfid machine.
public class Serverc {
final protected static char[] hexArray = "0123456789ABCDEF".toCharArray();
public static String bytesToHex(byte[] bytes) {
char[] hexChars = new char[bytes.length * 2];
for (int j = 0; j < bytes.length; j++) {
int v = bytes[j] & 0xFF;
hexChars[j * 2] = hexArray[v >>> 4];
hexChars[j * 2 + 1] = hexArray[v & 0x0F];
}
return new String(hexChars);
}
public static void connection() throws IOException {
ServerSocket ss = new ServerSocket(9888);//exce
ss.setSoTimeout(300000000);//exce
System.out.println("Waiting for client on port " + ss.getLocalPort() + "...");
while (true) {
Socket server = ss.accept();//exce
System.out.println("Just connected to " + server.getRemoteSocketAddress());
int available = 0;
DataInputStream in = new DataInputStream(server.getInputStream());//exce
int input = 0;
//BufferedReader br = new BufferedReader(in);
byte byteArr[] = new byte[28];
try {
//read till the end of stream
//while((input = in.available()) != -1)
while ((input = in.read(byteArr)) != -1) {
System.out.println("Size read is " + input);
System.out.println("Data is " + bytesToHex(byteArr));
}
//System.out.println("inside finally");
server.close();//exce
//System.out.println("outside finally");
} catch (SocketTimeoutException ex) {
System.out.println("Socket timed out!");
}
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String args[]) throws IOException {
Serverc obj = new Serverc();
obj.connection();
}
}
Here is my console
Waiting for client on port 9888...
Just connected to /106.208.71.50:61532
Size read is 28
Data is 55000016910001DB00FB63ABEEAFC1EC888F10263410050711148F3500000000
Size read is 28
Data is 55000016910001DB00FB63ABEEAFC1EC888F10263410050711148F3500000000
Size read is 28
Data is 55000016910001DB00FB63ABEEAFC1EC888F10263410050711148F3500000000
Size read is 28
Data is 55000016910001DB00FB63ABEEAFC1EC888F10263410050711148F3500000000
Size read is 28
Data is 55000016910001DB00FB63ABEEAFC1EC888F10263410050711148F3500000000
Here I need to remove 55000016 from the output.
Advance thanks
You could use Arrays.copyOfRange method to filter the unwanted bytes and save the result to a new byte array.
byte[] filteredByteArray = Arrays.copyOfRange(byteArr, 4, byteArr.length);
If you want to skip the first four bytes change this,
for (int j = 0; j < bytes.length; j++) {
to something like
for (int j = 4; j < bytes.length; j++) {
Or you might use String.substring(int)
bytesToHex(byteArr).substring(8); // <-- skip the first 4 bytes
You have a larger problem than skipping the 4 bytes at the start of each of your packets. Your code does this:
byte byteArr[] = new byte[28];
try {
while ((input = in.read(byteArr)) != -1) {
System.out.println("Size read is " + input);
System.out.println("Data is " + bytesToHex(byteArr));
}
(commented-out lines removed)
Note that you cannot guarantee that all 28 bytes will be read on each call to in.read(), but that your bytesToHex() method is assuming that 28 valid bytes are present in the array. You need to collect data that you read into the array until you have all of your packet before processing it, probably using a DataInputStream with the method readFully(byte[]). Then you can skip the first 4 bytes as suggested in the other answers.
It is best for you to skip the 4 bytes. But if you want to remove them, you should use this solution (your array may become massive). This algorithm is best you can get in Java for your problem. O(1) space , O(n) time.
void removeFourBytes(byte[] a) {
for (int i = 4; i < a.length; i++) {
a[i-4]=a[i];
}
for (int i = a.length - 1; i > a.length - 5; i--) {
a[i] = 0;
}
}
Second best option would be System.arrayCopy() - O(n) space, O(n) time.
private void readIncomingMessage() {
try {
StringBuilder builder = new StringBuilder();
InputStream is = socket.getInputStream();
int length = 1024;
byte[] array = new byte[length];
int n = 0;
while ((n = is.read(array, n, 100)) != -1) {
builder.append(new String(array));
if (checkIfComplete(builder.toString())) {
buildListItems(builder.toString(), null);
builder = new StringBuilder();
}
}
} catch (IOException e) {
Log.e("TCPclient", "Something went wrong while reading the socket");
}
}
Hi,
I want to read the stream per block of 100 bytes, convert those bytes into a string and than see if that strings fits certain conditions.
But when I debug I see that builder has a count of 3072.
And I see a string like (text, , , , , , , , , , text , , , , , , , , , text)
How can I just add the text to the stringbuilder?
thx :)
private void readIncomingMessage() {
try {
StringBuilder builder = new StringBuilder();
InputStream is = socket.getInputStream();
int length = 100;
byte[] array = new byte[length];
int n = 0;
while ((n = is.read(array, 0, length)) != -1) {
builder.append(new String(array, 0, n));
if (checkIfComplete(builder.toString())) {
buildListItems(builder.toString(), null);
builder = new StringBuilder();
}
}
} catch (IOException e) {
Log.e("TCPclient", "Something went wrong while reading the socket");
}
}
this solution did the trick for me.
any drawbacks with this solution?
2 problems:
you need to use the 'n' value when converting the bytes to a String. Specifically, use this String constructor String(byte[] bytes, int offset, int length)
when converting bytes to strings on arbitrary boundaries, like you are doing, you have the potential to corrupt multi-byte characters. You'd be better off putting an InputStreamReader on top if the 'is' and reading characters from that.
For more information read the documentation for read(byte[], int, int), new String(byte[]) and new String(byte[], int, int)
n will hold the number of bytes read in the last read operation - not the total number of bytes read. If you only want to read up to 100 bytes at a time, there is no need for a byte array of size 1024, 100 will do. When you create a String from a byte array, it uses the entire array (even if only half was able to be filled by reading), unless you tell it which parts of the array you want to use. Something like this should work, but there are still improvements you could make:
private void readIncomingMessage() {
try {
StringBuilder builder = new StringBuilder();
InputStream is = socket.getInputStream();
int length = 100;
byte[] array = new byte[length];
int pos = 0;
int n = 0;
while (pos != length && ((n = is.read(array, pos, length-pos)) != -1)) {
builder.append(new String(array, pos, n));
pos += n;
if (checkIfComplete(builder.toString())) {
buildListItems(builder.toString(), null);
builder = new StringBuilder();
pos = 0;
}
}
} catch (IOException e) {
Log.e("TCPclient", "Something went wrong while reading the socket");
}
}
I obviously don't know where is the problem!, First I ask the client to send me the Length of the byte[] he is going to send, then I read for its length like this.
int i = 323292; // length of incoming Byte[]
byte[] b = new byte[i];
int readBytes=inputStream.read(b,0,b.length);
But It always kept reading readBytes less than i. And I am sure that the client sends the whole byte[].
I tried to put it inside a loop, to read till my total number of read bytes is i, but I always get IndexOutOfBoundsException after the second Iteration! here is the code
boolean flag = true;
int i = 323292;
int threshold = 0;
byte[] b = new byte[i];
int read = 0;
while (flag) {
if (threshold < i) {
System.out.println(threshold);
try {
read = inputStreamFromClient.read(b, threshold, b.length);
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
threshold = threshold + read;
} else {
flag = false;
}
}
AnyIdeas?
This:
read = inputStreamFromClient.read(b, threshold, b.length);
should be:
read = inputStreamFromClient.read(b, threshold, b.length - threshold);
I tried to solve the problem in many ways but without success and I have also looked for information in this forum but with same results, so here we go.
I am actually doing a server daemon that accepts client requests and then it (the server) transfers all the files contained in a specific folder. I'm going to post the code of the sendFileData (on the server) and the receiveFileData (on the client).
The server uses:
public static void sendFileData(File file, Socket socket) throws FileNotFoundException, IOException, SocketException {
byte[] auxiliar = new byte[8192];
byte[] mybytearray = new byte[(int) file.length()];
int longitud = mybytearray.length;
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
bis.read(mybytearray, 0, longitud);
DataOutputStream os = new DataOutputStream(socket.getOutputStream());
int paquetes = longitud / 8187;
int resto = longitud % 8187;
int i = 0;
while(i<paquetes){//The length goes on the first 4 bytes and the 5th tells if there are more packets to send (8192 bytes or less).
byte[] bytes = ByteBuffer.allocate(4).putInt(8187).array();
auxiliar[0] = bytes[0];
auxiliar[1] = bytes[1];
auxiliar[2] = bytes[2];
auxiliar[3] = bytes[3];
auxiliar[4] = 1;
for(int j = 5; j < 8192; j++){
auxiliar[j] = mybytearray[i*8187+(j-5)];
}
os.write(auxiliar, 0, 8192);
i+=1;
}
if(resto > 0){
byte[] bytes = ByteBuffer.allocate(4).putInt(resto).array();
auxiliar[0] = bytes[0];
auxiliar[1] = bytes[1];
auxiliar[2] = bytes[2];
auxiliar[3] = bytes[3];
auxiliar[4] = 0;
for(int j = 5; j < resto+5; j++){
auxiliar[j] = mybytearray[i*8187+(j-5)];
}
os.write(auxiliar, 0, resto+5);
}
os.flush();
}
And in the client side:
public static void receiveFileData(String nombreFichero, Socket s) throws IOException{
File monitored = new File(nombreFichero);
if(monitored.exists() == false){
monitored.createNewFile();
}
byte[] mybytearray;
DataInputStream is = new DataInputStream(s.getInputStream());
FileOutputStream fos = new FileOutputStream(monitored);
BufferedOutputStream bos = new BufferedOutputStream(fos);
int bytesRead = 0;
int hasNext = 1;
do {
bytesRead = is.readInt();//Leo longitud
try {
Thread.sleep(1);// HERE!!!!
} catch (InterruptedException e) {
}
// System.out.println("Bytes read "+bytesRead );
if(bytesRead <= 8187 && bytesRead > 0){
// System.out.println("Bytes leídos "+bytesRead );
hasNext = is.readByte();//Leo si hay más datos por enviar
mybytearray = new byte[bytesRead];
is.read(mybytearray);
if(monitored.exists()){
synchronized(monitored){
bos.write(mybytearray, 0, mybytearray.length);
}
}
mybytearray = null;
}else{
System.out.println("Fuera de rango "+bytesRead);
}
}while(hasNext == 1);
bos.close();
mybytearray = null;
System.out.println("Fichero recibido: "+monitored.getAbsolutePath());
}
In the receiveFileData code, if I do not put a Thread.sleep(1) or a System.out.println() or whatever who takes time to execute, I am not receiving the data in the correct way on the client, because readInt() returns a very high number randomly negative or positive (which implies Heap out of memory and other exceptions).
Sure it's something about synchronization but I think the transfering schema between the two methods is correct (maybe the client is too slow and server too fast).
What is happening?? Because I do not want to put a Thread.sleep, this is not good programming here I think.
Thank you so much!
is.read(bytes) is not guaranteed to fill the supplied byte array. You need to check its return value to see how many bytes were read or (better) use readFully().
The sleep() probably just allows time for all bytes to have been returned from the socket.