Problem
How to send UTF-8 data between the server and the client, if I can use on client only
inputStream.read()
?
Docs
Reads a single byte from this stream and returns it as an integer in
the range from 0 to 255. Returns -1 if the end of the stream has been
reached.
Without reader.readLine() and any another. (With reader I cant see end of stream)
Help please!
(full code:)
int c;
String str = new String();
while ((c = inputStream.read( )) != -1)
{
char ch = (char)c;
if(ch == '\n')
{
Log.v("", str);
final String data = str;
runOnUiThread(new Runnable()
{
#Override
public void run()
{
String put[] = data.split("#");
try
{
//cmd parsing
}
catch(Exception e)
{
//stop connection
}
}
});
str = "";
}else{
str += Character.toString(ch);
}
}
//Communication error
Help please
You might want to take a look at this previous post. There's a couple of good options on there. The read() method can be overloaded with different parameters, so you can read one byte, or n bytes. Check out the full documentation here. Basically, you'll have to read in the raw bytes, then convert them to ASCII characters. Also, I'm curious as to why you can't use BufferedReader or an equivalent class?
Related
I am working on a project that involves communication between an Android Uno and an Android phone. The phone sends a request signal "*" that once received, the Arduino sends random integers in a loop. Right now, the Android device is receiving the message but it is showing up as boxed question marks, and not receiving all of the messages. Any ideas? Thank you so much!
Arduino code:
#include <SoftwareSerial.h>
const int RX_PIN = 0;
const int TX_PIN = 1;
SoftwareSerial bluetooth(RX_PIN, TX_PIN);
char commandChar;
void setup (){
bluetooth.begin (9600);
Serial.begin(38400);
}
void loop () {
if(bluetooth.available()){
commandChar = bluetooth.read();
switch(commandChar){
case '*':
Serial.println("Got the request code");
for(int i = 0; i < 10; i++){
bluetooth.print(random(21));
}
break;
}
}
}
Android code:
public void run() {
initializeConnection();
byte[] buffer = new byte[256];
int bytes;
// Keep looping to listen for received messages
while (true) {
try {
bytes = mmInStream.read(buffer);//read bytes from input buffer
String readMessage = new String(buffer, 0, bytes);
Log.e("Received Message: ", readMessage);
} catch (IOException e) {
break;
}
}
}
public void initializeConnection() {
try {
PrintWriter out;
out = new PrintWriter(mmOutStream, true);
out.println("*");
out.flush();
}catch (NullPointerException NPE) {
}
}
Console output:
08-13 19:02:46.546 4019-4128/? E/Received Message:: �
08-13 19:02:46.596 4019-4128/? E/Received Message:: ����
Ah I think I spot the problem. Random numbers are being sent from the arduino to the app, and the app is logging these bytes as ascii literals. Instead of sending random numbers, try sending well-formed ascii (visual characters).
You can send the hex bytes [0x68,0x65,0x6c,0x6c,0x6f] for "hello", or use SoftwareSerialPrint's built-in HEX option.
So change it to this, see if that works.
bluetooth.print(random(21), HEX);
Edit:
Let's try this on the app side instead. This will convert the received bytes into a hexadecimal string representation so we can see it in ascii properly.
bytes = mmInStream.read(buffer);//read bytes from input buffer
StringBuilder sb = new StringBuilder(bytes * 2);
for(byte b: buffer)
sb.append(String.format("%02x", b));
Log.e("Received Message: ", sb.toString());
I am developing Client-Server application in C++ using Qt framework, but the clients can be android phones and computers(Qt client app)
Now i'm having troubles to handle Reception of data on the server side; the server is not receiving data properly.
First, I got things working nicely between the server(Qt app) and the client(Qt app) using these methods for sending and receiving:
The size of the message is kept at the beginning of the packet to help check whether the whole message is received or not.
This is the method to send message to the clients
void Server::send(const QString &message)
{
QByteArray paquet;
QDataStream out(&paquet, QIODevice::WriteOnly);
out << (quint16) 0; // just put 0 at the head of the paquet to reserve place to put the size of the message
out << message; // adding the message
out.device()->seek(0); // coming back to the head of the paquet
out << (quint16) (paquet.size() - sizeof(quint16)); // replace the 0 value by the real size
clientSocket->write(paquet); //sending...
}
This slot is called every time a single paquet is received.
void Server::dataReceived()
{
forever
{
// 1 : a packet has arrived from any client
// getting the socket of that client (recherche du QTcpSocket du client)
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QDataStream in(socket);
if (dataSize == 0) // if we don't know the size of data we are suppose to receive...
{
if (socket->bytesAvailable() < (int)sizeof(quint16)) // we haven't yet receive the size of the data completly then return...
return;
in >> dataSize; // now we know the amount of data we should get
}
if (socket->bytesAvailable() < dataSize)
return;
// Here we are sure we got the whole data then we can startreadind
QString message;
in >> message;
//Processing....
dataSize = 0; // re-initialize for the coming data
}
}
This is working well when the server is talking with the Qt app Client, because the same methods are used there, and the size of quint16 will remain the same hover it doesn't work with android client, then i tried another way in which i wanted to ignore the size of the message sent, but format the message in a way such that i can know where it starts and where it ends, then with some controls i can get it however i'm stuck here, cause the data read doesn't contain anything when printed, but his size has a value(which even vary according to the amount of text the client send)!
void Server::dataReceived() // a packet is received!
{
QTcpSocket *socket = qobject_cast<QTcpSocket *>(sender());
if (socket == 0)
return;
QByteArray data= socket->readAll(); //reading all data available
QString message(data)
qDebug() << data; // this prints nothing!
qDebug() << data.size();// But this prints a non null number, wich means we got something, and that number varies according to the amount of text sent!
qDebug() << message; // this also prints notghing!
}
PS: it's not working even for the Qt app Client.
Can you help me find out what's wrong, i'm a bit confused how the tcp protocol is handling the data, and if you could and also advise me a good way for doing this.
here is the android class I made for the purpose
class QTcpSocket implements Runnable {
private String ip="";
private int port;
private Socket socket;
private PrintWriter printWriter;
private DataOutputStream dataOutputStream;
private DataInputStream dataInputStream;
public QTcpSocket(String ip, int port) {
this.ip = ip;
this.port = port;
}
public void setIp(String ip) {
this.ip = ip;
}
public String getIp() {
return this.ip;
}
public void setPort(int port) {
this.port = port;
}
public void run() {
try {
socket = new Socket(this.ip, this.port);
dataOutputStream = new DataOutputStream( socket.getOutputStream() );
dataInputStream = new DataInputStream(socket.getInputStream());
String response = dataInputStream.readUTF();
dataOutputStream.writeUTF("Hello server!");
} catch (IOException e) {
e.printStackTrace();
}
}
public void sendMessage(String message) {
try {
dataOutputStream.writeUTF(message);
}catch (IOException e) {
e.printStackTrace();
}
}
public void disconnect() {
try {
printWriter.flush();
printWriter.close();
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
public boolean isClosed() {
return socket.isClosed();
}
}
Replace in 'data' all bytes with value 0 by value 20 and print again. I think you see nothing printed because the first byte is 0. You could also replace with 'X'. Did you already replace writeUTF() by write() ?
20 is the space character. But then you also see nothing printed so better use a X char. Strings get printed until a \0 char (which indicates the end of a string) is met. Because nothing was printed i supposed one right at the beginning. So writeUTF causes that leading 0. I could only explain that if all chars had doubled. What was the first char you sent?
But now: send size-of-message first so it equals your qt client.
I'm developing an app to communicate with a PCB board via bluetooth.
I receive a string from the PCB board to my app every 50ms. This string has the next structure:
start_byte(1byte)/battery _level(1byte)/speed(1byte)/mode(1byte)
So I'll receive a string like this (I'll put it in hex):
80464B11
each 50ms.
This is the code. First this is the ConnectedThread which listens for the communication and that sends the received message to the mainActivity:
public void run() {
byte[] buffer = new byte[1024];
int readed;
while (true) {
try {
readed = inputStream.read(buffer);
if (readed > 0) {
final byte[] temp = new byte [readed];
System.arraycopy(buffer, 0, temp, 0, readed);
activity.runOnUiThread(new Runnable() {
#Override
public void run() {
/*Sends message to UI*/
connectionListener.msgRead(temp);
}
});
}
} catch (IOException e) {
...
break;
}
}
Then in MainActivity I operate with the received string to extract from it each value.
#Override
public void msgRead(byte[] buffer) {
String income = byteArrayToHex(buffer);
...
Here the next step would be to check for the start_byte and after this, get the other values.
But here comes my doubt. This string will be received each 50ms, so I'll be receiving something like this:
80464B1180464B1180464B1180464B1180464B1180464B1180464B1180464B1180464B11...
So, what I do to check for the start_byte is this:
String start_byte = income.substring(0, 2);
And then, if that matches with the start_byte value, I extract the rest of the values:
if (start_byte.equals("80")) {
...
Is my approach correct to face this? Won't the buffer overflow? How can I correctly check for the start_byte to the get the other values?
maybe it is usefull to just use the read() function. This function is blocking until one byte has been read. So you can make something like this:
int[] yourArray = new int[4];
for(int i = 0; i < 4; i++)
{
yourArray[i] = inputStream.read();
}
so now your string is devived in 4 int's stored in a array.
maybe this helps you out in some sort of way
I have faced the problem this way. I've created a Queue in the ConnectedThread. Each time I receive a byte[] I put it into the Queue.
LinkedList<Byte> dataQueue = new LinkedList<Byte>();
int i = 0;
while (i< temp.length) {
dataQueue.add(temp[i]);
i++;
}
Then, when I want to get them I do:
byte readed_byte = dataQueue.pop();
This way I get a byte from the head of the queue each time I do pop().
I am doing Client server communication in java successfully but now i need to write client in Android rather the java.
client: public class ExampleClient2 {
public static void main(String[] args) throws IOException,
InterruptedException {
int port = 1114;
SocketChannel channel = SocketChannel.open();
// we open this channel in non blocking mode
channel.configureBlocking(false);
channel.connect(new InetSocketAddress("192.168.1.88", port));
if(!channel.isConnected())
{
while (!channel.finishConnect()) {
System.out.println("still connecting");
}
}
System.out.println("connected...");
while (true) {
// see if any message has been received
ByteBuffer bufferA = ByteBuffer.allocate(60);
int count = 0;
String message = "";
while ((count = channel.read(bufferA)) > 0) {
// flip the buffer to start reading
bufferA.flip();
message += Charset.defaultCharset().decode(bufferA);
}
if (message.length() > 0) {
System.out.println("message " + message);
if(message.contains("stop"))
{
System.out.println("Has stop messages");
// break;
}
else
{
// write some data into the channel
CharBuffer buffer = CharBuffer.wrap("Hello Server stop from client2 from 88");
while (buffer.hasRemaining()) {
channel.write(Charset.defaultCharset().encode(buffer));
}
}
message = "";
}
}
}
}
this code is running successfully in java but in android it consuming lots of memory and not running reliably, due to its while (true) loop its like polling , plz let me know some solution that without polling i can read and write the data.
Thanks.
You need to compact() the buffer after calling decode() (or get(), or write(), anything that takes data out of the buffer).
Youu shouldn't allocate a new buffer every time around that while loop, and you should break out of it if read() returned -1. I don't actually see a need for the while loop at all.
I have a device here that I can send a status request command to, and then I read it using
bytes = mmInStream.read(statusBuffer);
I'm having trouble when it changes it's status though. Sometimes I will get back the current status, other times the program will hang on that line and not do anything else. It doesn't crash, move onto the next line or anything. I can only move on by turning off the device and severing the connection.
We have a blackberry torch here that does not have this error at all so it must be my code.
Can anyone give me some troubleshooting tips? Below is the while loop that reads the devices current status.
while (true) {
getStatus();
try {
bytes = 0;
while(bytes < 1){
bytes = mmInStream.read(statusBuffer);
if (bytes != 0){
response = new String(statusBuffer);
//Handle response code
}
}
}
} catch (Exception e) {
Log.e(TAG, "disconnected FROM WHILE TRUE LOOP", e);
connectionLost();
break;
}
}
If there is no byte available, -1 is returned by read, you miss your comparison and you go on looping.
If your line ends with a \n char it would be far easier to read it through an BufferedReader for instance. Anyhow, your loop is not very well designed.
do
{
//read bytes
//store the result in byteRead
//if( byteRead != -1 )
//build a string
}//do
while( byteRead != -1 )
Regards,
Stéphane