-1

I wrote a piece of server code in C and I would like to send data continuously to my client application every iteration.

while (1)
{
    startInt = mymillis();//capture starting time

    Sensor_raw_data_float = Sensor_Read_Values_();
    float data = Sensor_raw_data_float.x * 0.007;

    send(sockfd, &data , sizeof(float),0);//Send to client

    //Wait until 5ms
    while (mymillis() - startInt < (5))
    {
        usleep(100);
    }

}

I tried using "snprintf" to convert my float data to string before sending but I realise the whole system start to slow down and lagged alot.

As such I tried to do the editing on the client code. Attached is the main part of my client code that is related to what i am trying to do

    import android.os.Bundle;
    import android.os.Handler;
    import android.os.Message;
    import android.support.v7.app.AppCompatActivity;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;

public class MainActivity extends AppCompatActivity {

EditText editTextAddress, editTextPort, editTextMsg;
Button buttonConnect, buttonDisconnect, buttonSend;
TextView textViewState, textViewRx;

ClientHandler clientHandler;
ClientThread clientThread;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

textViewRx = (TextView) findViewById(R.id.received);

    clientHandler = new ClientHandler(this);
}

private void updateState(String state){
    textViewState.setText(state);
}

private void updateRxMsg(String rxmsg){
    textViewRx.append(rxmsg + "\n");

}


public static class ClientHandler extends Handler {
    public static final int UPDATE_STATE = 0;
    public static final int UPDATE_MSG = 1;
    public static final int UPDATE_END = 2;
    private MainActivity parent;

    public ClientHandler(MainActivity parent) {
        super();
        this.parent = parent;
    }

    @Override
    public void handleMessage(Message msg) {

        switch (msg.what){
            case UPDATE_STATE:
                parent.updateState((String)msg.obj);
                break;
            case UPDATE_MSG:
                parent.updateRxMsg((String)msg.obj);
                break;
            case UPDATE_END:
                parent.clientEnd();
                break;
            default:
                super.handleMessage(msg);
        }

    }

}

}

I tried to edit my updateRxMsg(String rxmsg)'s code to

 private void updateRxMsg(String rxmsg){
    private void updateRxMsg(String rxmsg){
    //textViewRx.append(rxmsg + "\n");
    float f = Float.parseFloat(rxmsg);
    String mytext=Float.toString(f);
    textViewRx.append(mytext + "\n");
}

}

but i am still getting garbage printed out on my TextView. I am not able to figure out what is the problem but i do suspect it is related to encoding. I would like to get some help on how to get my float data from my server to my client side.

Update: Attach is the codes for my bufferreader etc.., initially i thought that the problem does not lies here but i will post it here too.

public class ClientThread extends Thread{

String dstAddress;
int dstPort;
private boolean running;
MainActivity.ClientHandler handler;

Socket socket;
PrintWriter printWriter=null;
BufferedReader bufferedReader;

public ClientThread(String addr, int port, MainActivity.ClientHandler handler) {
    super();
    dstAddress = addr;
    dstPort = port;
    this.handler = handler;
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
            .permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

public void setRunning(boolean running){
    this.running = running;
}

private void sendState(String state){
    handler.sendMessage(
            Message.obtain(handler,
                    MainActivity.ClientHandler.UPDATE_STATE, state));
}

public void txMsg(String msgToSend){
    if(printWriter != null){
        printWriter.println(msgToSend);
    }
}

@Override
public void run() {
    sendState("connecting...");

    running = true;

    try {
        socket = new Socket(dstAddress, dstPort);
        sendState("connected");

        OutputStream outputStream = socket.getOutputStream();
        printWriter = new PrintWriter(outputStream, true);

        InputStream inputStream = socket.getInputStream();
        InputStreamReader inputStreamReader =
                new InputStreamReader(inputStream);
        bufferedReader = new BufferedReader(inputStreamReader);

        while(running){

            //bufferedReader block the code
            String line = bufferedReader.readLine();
            if(line != null){
                handler.sendMessage(
                        Message.obtain(handler,
                                MainActivity.ClientHandler.UPDATE_MSG, line));
            }

        }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(bufferedReader != null){
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if(printWriter != null){
            printWriter.close();
        }

        if(socket != null){
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    handler.sendEmptyMessage(MainActivity.ClientHandler.UPDATE_END);
}

}

I updated my code to:

import android.os.Message;
import android.os.StrictMode;

import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.nio.ByteBuffer;

public class ClientThread extends Thread{

String dstAddress;
int dstPort;
private boolean running;
MainActivity.ClientHandler handler;

Socket socket;
PrintWriter printWriter=null;
BufferedReader bufferedReader;

public ClientThread(String addr, int port, MainActivity.ClientHandler handler) {
    super();
    dstAddress = addr;
    dstPort = port;
    this.handler = handler;
    StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
            .permitAll().build();
    StrictMode.setThreadPolicy(policy);
}

public void setRunning(boolean running){
    this.running = running;
}

private void sendState(String state){
    handler.sendMessage(
            Message.obtain(handler,
                    MainActivity.ClientHandler.UPDATE_STATE, state));
}

public void txMsg(String msgToSend){
    if(printWriter != null){
        printWriter.println(msgToSend);
    }
}

@Override
public void run() {
    sendState("connecting...");

    running = true;

    try {
        socket = new Socket(dstAddress, dstPort);
        sendState("connected");

        OutputStream outputStream = socket.getOutputStream();
        printWriter = new PrintWriter(outputStream, true);

        InputStream inputStream = socket.getInputStream();
        InputStreamReader inputStreamReader =
                new InputStreamReader(inputStream);
        bufferedReader = new BufferedReader(inputStreamReader);

        int bufferSize = 8192;

        ByteBuffer bf = ByteBuffer.allocate(bufferSize);
            BufferedInputStream inFromServer = new BufferedInputStream(socket.getInputStream());
            while (true) {
                int b = inFromServer.read();
                if (b == -1) {
                    break;
                }
                bf.put( (byte) b);

                handler.sendMessage(
                        Message.obtain(handler,
                                MainActivity.ClientHandler.UPDATE_MSG, (byte) b));
            }

       // while(running){

            //bufferedReader block the code
        //    String line = bufferedReader.readLine();
       //     if(line != null){
       //         handler.sendMessage(
       //                 Message.obtain(handler,
       //                         MainActivity.ClientHandler.UPDATE_MSG, line));
      //      }

      //  }

    } catch (IOException e) {
        e.printStackTrace();
    } finally {
        if(bufferedReader != null){
            try {
                bufferedReader.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        if(printWriter != null){
            printWriter.close();
        }

        if(socket != null){
            try {
                socket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    handler.sendEmptyMessage(MainActivity.ClientHandler.UPDATE_END);
}

}

I am very confuse on what should be change inorder for bytebuffer to work and is unsure if i changed it correctly. Thank You!

D.Bryan
  • 19
  • 6

3 Answers3

1

Make up your mind.

If you're sending the float directly, as per the code you posted, read it with DataInputStream.readFloat(). If you're lucky and the endianness is the same, you're done.

Or convert it to a string, send it as a line, read it as a line, and parse it back to float.

Not a mixture of the two.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • Hi EJP, Yes, you are right I am sending float directly. I tried the second method you mentioned, but my server becomes very lagged. Is it okay if you guide me on how to edit my code to useDataInputStream.readFloat()? I am not really sure what are the necessary changes to be made. – D.Bryan Feb 27 '18 at 01:29
  • Eh? Create a `DataInputStream`, and call `readFloat()` on it. No mystery. – user207421 Feb 27 '18 at 02:32
0

As a workaround I'd suggest you try converting the float to an integer before sending (just multiply by 10 to the power of the precision you'd like to have) and see what data you get. That could help you narrow down the problem. If you really insist on using floating point numbers you might want to refer to this question : How are floating point numbers are stored in memory?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
0

When transmitting the float as binary data, bytes, I would assume that msg.obj is actually a byte array. When the float is sent from an Intel little endian platform as 4 bytes, the following code should work.

       case UPDATE_MSG:
            byte[] flt = (byte[])msg.obj;
            if (flt.length != 4) {
                throw new IllegalStateException();
            }
            float x = ByteBuffer.wrap(flt)
                .order(ByteOrder.LITTLE_ENDIAN)
                .getFloat();
            break;

As you did not receive a ClassCastException I still have some doubts. However binary data cannot be held by a String, that uses internally Unicode, as UTF-16, which can corrupt binary data.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
  • Hi Joop eggen,I tried your code and the apps crashes immediately on startup. Is it because I am using String instead of Byte? I just updated my post with thecodes that consist of the bufferedReader. The float is send from a ARMs linux machine. – D.Bryan Feb 26 '18 at 17:03