I have created a socket that connects to a Raspberry pi hot spot. I am able to successfully connect to it and send a string to the pi. However, since I have tried to implement read functionality to get data from the pi, I have had some issues.
Every time I run the while loop or just have a "response = myBufRead.readLine()", the program stalls.
private class StatusCheck extends AsyncTask<Void, Void, Void> {
#Override
protected Void doInBackground(Void... params) {
//debug vibrations and text
if(vibrate) {
Vibrator vib = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
vib.vibrate(100);
}
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
Log.d(debugStr, "In initial connect");
mySocket = new Socket(serverAddr, SERVERPORT);
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
} finally {
if (mySocket == null) {
str1 = "Socket became null";
return null;
}
str1 = "Connected";
try {
PrintWriter myPrintWriter = new PrintWriter(mySocket.getOutputStream(), true);
InputStreamReader myInputStreamRead = new InputStreamReader(mySocket.getInputStream());
BufferedReader myBufRead = new BufferedReader(myInputStreamRead);
Log.d(debugStr, "In out created");
myPrintWriter.write(recordName);
Log.d(debugStr, String.valueOf(myBufRead.ready()));
Log.d(debugStr, "About to enter while loop");
while((response = myBufRead.readLine()) != null) {
Log.d(debugStr, "in while loop");
response = myBufRead.readLine();
Log.d(debugStr, String.valueOf(myBufRead.ready()));
Log.d(debugStr, myBufRead.readLine());
Log.d(debugStr, String.valueOf(myBufRead.ready()));
}
Log.d(debugStr, "out of while loop");
myPrintWriter.close();
myInputStreamRead.close();
myBufRead.close();
} catch (IOException e1) {
e1.printStackTrace();
}
try {
mySocket.close();
} catch (IOException e1) {
e1.printStackTrace();
}
return null;
}
}
}
Anyone know why this is happening? Any help is appreciated, thanks!
BuffereadReader.readLine() is a blocking method, so it will wait and, as you say, "stall" its thread until it has something to read. Are you calling flush() after you write to the stream from your pi?
Another issue might be that readLine() will wait for a complete line, i.e. it will wait until it reads a line separator character. Are you sending a line separator character from your pi? See Socket Multithreading - Reading input stream pauses thread
You can do (from the pi end, assuming you're using a BufferedWriter):
bufferedWriter.write(text);
bufferedWriter.newLine();
bufferedWriter.flush();
Related
It's my first question in here. I hope i can find answer. Subject is that, i have server (arduino). it send and receive data.it send data when take a data from client side(android). Android side is send data when push button. Also android has use Speech to Text (google API).So when we push button or use speechrecognation, client side send a data.But it reads socket continuously. I have two kind android device. One device work well about data receiving but it is not good about speechrecognation. One device very well about voice but after a while socket is happened useless. We must push reset button on arduino and reset android app. (My first android device version is 5.1.1 second is 6.0). Sorry for my english. I hope i can tell my problem :)
.
.
.
public void senddata(String asd){
try {
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())),
true);
out.println(asd);
out.flush();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
.
.
.
class ClientThread implements Runnable {
#Override
public void run() {
BufferedReader inStream = null;
try {
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
//socket.setSoTimeout(1000);
// Get the input and output streams
inStream = new BufferedReader(new
InputStreamReader(socket.getInputStream()));
// Confirm that the socket opened
// Read messages in a loop until disconnected
while( true){
String msg= inStream.readLine();
Log.e("GELENLER::::",msg);
gelenkomut=msg;
runOnUiThread(new Runnable() {
#Override
public void run() {
// TODO Auto-generated method stub
gelenparse(gelenkomut);
}
});
// Send it to the UI thread
}
} catch (UnknownHostException e1) {
e1.printStackTrace();
} catch (IOException e1) {
e1.printStackTrace();
}
finally {
try {
inStream.reset();
inStream.
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
I want to know if is possible to close the current java app util another has done some task, my code is this:
private static void callJar(String jardir) throws IOException, InterruptedException {
// jardir contains the excecution command
Process p = Runtime.getRuntime().exec(jardir);
synchronized (p) {
// Here I want to wait for p for a signal but not when p has finished
// but waitFor() do the second
p.waitFor();
}
// If the other jar is correctly loaded, close this jar
System.exit(0);
}
The string jardir contains the excecution command that will start the other process that I will be listening, something like this:
jardir = "javaw -jar \\path\\to\\anotherjar.jar"
For now, callJar() opens this process and then close the current until the process that I started has been terminated. In other words, close A until B has been closed.
But what I want to do is to close A until B send a signal (B will continue to exist).
Is there a way to listen for a signal from the process that I started?
After searching for an answer, I finally found a solution, maybe this will work for someone so here is what I did:
Based on this answer and this site, I opted to create a communication between two Java apps using the java.net libraries.
In the process A, I have a method that create a server communication and just waits until it receive a message from process B...
private static boolean listen2ExternalProcess() {
ServerSocket server = null;
Socket serverSocked = null;
String line;
BufferedReader inputReader = null;
try {
server = new ServerSocket(3333);
serverSocked = server.accept();
inputReader = new BufferedReader(
new InputStreamReader(serverSocked.getInputStream()));
while (true) {
line = inputReader.readLine();
log.info("Client says: " + line);
if (line.equals("Kill yourself :D")) {
return true;
}
}
} catch (UnknownHostException e) {
log.error("Don't know about this, " + e);
return false;
} catch (IOException e) {
log.error("Couldn't get IO for the connection, " + e);
return false;
} finally {
try {
if(serverSocked != null) serverSocked.close();
if(inputReader != null) inputReader.close();
} catch (IOException ex) {
log.error("Couldn't get IO for the connection, " + ex);
return false;
}
}
}
this method will return true if the message has been received, then I can proceed to terminate process A.
In the process B, I have a method that just send a message to a socket when I need it...
public static void talk2ExternalProcess() {
Socket socket = null;
BufferedWriter outputWriter = null;
try {
socket = new Socket("localhost", 3333);
outputWriter = new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream()));
} catch (UnknownHostException e) {
log.error("Don't know about host: localhost, " + e);
} catch (IOException e) {
log.error("Couldn't get IO for the connection to localhost, " + e);
}
if (socket != null && outputWriter != null) {
try {
outputWriter.write("Kill yourself :D");
} catch (UnknownHostException e) {
log.error("Trying to connect to unkown host: " + e);
} catch (IOException e) {
log.error("IO Exception: " + e);
} finally {
try {
outputWriter.close();
socket.close();
} catch (IOException ex) {
log.error("IO Exception: " + ex);
}
}
} else {
log.warn("null socket or outputwriter");
}
}
finally, I just change the callJar method to something like this:
private static void callJar(String jardir) throws IOException {
Runtime.getRuntime().exec(jardir);
if (listen2ExternalProcess()) {
System.exit(0);
} else {
log.warn("Something went wrong...");
}
}
I would like to find an easier answer, but for now, this works for me.
I build a TCP multicast chat application using asynctask.
I am also trying to order the message in FIFO and causal order.
However, when I try to send a lot of messages simultaneously for testing, it misses some messages but I can't find the reason.
I have tried as hard as I can to improve the performance of the program because I thought the performance could be the reason. but still having the same issue.
I attached some important part of my code.
Most of all,
private class ServerTask extends AsyncTask<ServerSocket, String, Void> {
#Override
protected Void doInBackground(ServerSocket... sockets){
ServerSocket serverSocket = sockets[0];
Socket socket = new Socket();
try {
while(true) {
socket = serverSocket.accept();
InputStream inputstream = socket.getInputStream();
DataInputStream in = new DataInputStream(new BufferedInputStream(inputstream));
String msg = ""+in.readUTF();
String time = ""+in.readUTF();
String temp = time+"||"+msg;
publishProgress(temp);
in.close();
}} catch (IOException e) {
e.printStackTrace();
} finally{
try {
socket.close();
serverSocket.close();////
} catch (IOException e) {
e.printStackTrace();
}
}
return null;
}
Here is onProgressUpdate.
protected void onProgressUpdate(String...strings) {
/*
* The following code displays what is received in doInBackground().
*/
String strReceived = strings[0].trim();
TextView remoteTextView = (TextView) findViewById(R.id.textView1);
remoteTextView.append(strReceived + "\t\n");
try {
sequencer(strReceived);
} catch (ParseException e) {
e.printStackTrace();
}
return;
}
}
..
private class ClientTask extends AsyncTask<String, Void, Void> {
#Override
protected Void doInBackground(String... msgs) {
Date currentDate= new Date();
Timestamp time = new Timestamp(currentDate.getTime());
Message temp = new Message(myPort, msgs[0], time);////
try {
for(int i = 0; i <= 2; i++) {
Socket socket = new Socket();
socket.connect(new InetSocketAddress(InetAddress.getByAddress(new byte[]{10, 0, 2, 2}),
Integer.parseInt(REMOTE_PORTS[i])), 1000);
socket.setTcpNoDelay(true);
OutputStream outputStream = socket.getOutputStream();
DataOutputStream o = new DataOutputStream(new BufferedOutputStream(outputStream));
o.writeUTF(msgs[0]);
o.writeUTF(""+time);
o.flush();////
socket.close();
}
}
catch (UnknownHostException e) {
Log.e(TAG, "ClientTask UnknownHostException");
} catch (IOException e) {
Log.e(TAG, "ClientTask socket IOException");
}
return null;
}
Can you find the part causes the problem?
Sequencing / Queueing /Acknowledgement all these things are part of TCP so it is done by the protocol itself so you do not need to do all those explicitly from your code. There are still some parts of your code that can be improved. Like:
String time = received.split("\\|\\|")[0];
String msgToSend = received.split("\\|\\|")[1];
//Instead of doing this, its better to do this:
String peices[]=received.split("\\|\\|");
String msgToSend=peices[1];
String time=peices[0]
Also you can check if you are receiving all the raw messages and if its during the parsing process the messages are getting lost using a log:
Log.d("RAW_MESSAGE","Message Received: "+temp); //in your doInBackground
If you get all the messages that you send in this log, then there is nothing wrong with the protocol or the sending/receiving process rather there is a problem while you are processing the message. Also for these types of use-cases, try using the Service component rather than AsyncTask.
I hope this helps.
First of all multicast is over UDP, not TCP.
And if you want to create a multicast app, you should use multicastsocket
http://developer.android.com/reference/java/net/MulticastSocket.html
I'm getting mad trying to read data from a socket. I tried all and all, I think that my code should work but didn't.
My intention is to only run the following method on the onCreate. First I create a Thread to run all the things that are related to the network. Then, I create the scoket object and I read the inputstream of the socket. In this moment, in an infinit loop, I read the inputstream using readLine as explained saw on this answer. Finally, I do what I want with the data that came by the socket.
I don't know how much data will be sended by the server. And it would be in json, but this doesn't matter.
Here my code
public void receiveMsgs(){
new Thread(new Runnable(){
#Override
public void run() {
BufferedReader in = null;
try {
Log.d("NETWORK-RECEIVE", "Trying to connect to socket...");
Socket socket;
InetAddress serverAddr = InetAddress.getByName(SERVER_IP);
socket = new Socket(serverAddr, SERVERPORT);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
if(socket.isConnected()){
Log.d("NETWORK-RECEIVE", "The connection have been stablished");
}
} catch (IOException e) {
e.printStackTrace();
Log.d("NETWORK-RECEIVE", "Something goes wrong: IOException");
}
while(true){
String msg = null;
try {
StringBuilder total = new StringBuilder();
String line;
while ((line = in.readLine()) != null) {
total.append(line);
}
msg = total.toString();
Log.d("NETWORK-RECEIVE","Message readed!:"+msg);
} catch (IOException e) {
e.printStackTrace();
Log.d("NETWORK-RECEIVE", "Something goes wrong: IOException");
}
if(msg == null){
Log.d("NETWORK-RECEIVE", "Message is null");
break;
}
else{
//Do what I want
Log.d("NETWORK-RECEIVE", "something");
}
}
}
}).start();
}
Ever look at square's OKHttp or Retrofit?
http://square.github.io/okhttp/#examples
&
http://square.github.io/retrofit/
Seems easier than sockets. Do you really need sockets?
I'm trying to write this program which updates itself on the current status of a variable. How I intended it to work is by having a timed task to constantly send the string "update" to the server. The server will recognize the string and will send the necessary values for the variable on the android device. However, I am facing some problems. The string "update" is sending without error but when the corresponding value from the server is sent back, the program does not seem to be able to read the reply. Here is the code:
//Open socket and initialize data streams
try {
socket = new Socket(serverIpAddress, applicationport);
//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//in = new DataInputStream(socket.getInputStream());
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
} catch (UnknownHostException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
} catch (IOException ex) {
// TODO Auto-generated catch block
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
}
//Create new daemon timer
updateData = new Timer(true);
updateData.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
out.println("update");
UpdateMethod();
}//run
}, 1000, 10000);//schedule the delays start/interval here
};
private void UpdateMethod() {
//This method is called directly by the timer
//and runs in the same thread as the timer.
//It calls the method that will work with the UI
//through the runOnUiThread method.
this.runOnUiThread(Timer_Tick);
};//timermethod
private Runnable Timer_Tick = new Runnable() {
public void run() {
try {
//in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
//String getx1 = null;
//getx1 = in.readLine();
//if (getx1 != null) {
//float updatex1 = Float.parseFloat(getx1);
//get_x1 = getx1;
//}
in = new DataInputStream(socket.getInputStream());
/*try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
x1display = (TextView) findViewById(R.id.x1display);
x1display.setText(in.readUTF());
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
finally {
if (in != null){
try {
in.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
};
As you can see, I have tried experimenting with both DataInputStream and BufferedReader as well but to no avail.
Edit: It seems that trying to read from the input stream is causing my UI to freeze up. I have no idea what is wrong as my code seems to be without errors..
Any help or advice would be greatly appreciated!
Thank you!
The code looks fine to me. But its not working so looks like you need to chop it up.
Test if the socket stuff is working without the Timer. Make a socket connection and read its response without the Timer and UI code
If that works, introduce the Timer but not the UI code
If that works, do the whole thing (which is failing now)
Somewhere in this test process you should be able to find the culprit
As you have already said, reading blocks the thread. You shouldn't ever read something inside the UI thread! Furthermore, as I remember correctly, closing input before closing output does some nasty things. I would suggest closing the socket instead and putting the BufferedReader back in. This is how it should look like:
//Open socket and initialize data streams
try {
socket = new Socket(serverIpAddress, applicationport);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
} catch (UnknownHostException ex) {
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
} catch (IOException ex) {
ex.printStackTrace();
ShowDialog("Login Error" + ex.getMessage());
}
//Create new daemon timer
updateData = new Timer(true);
updateData.scheduleAtFixedRate(new TimerTask() {
#Override
public void run() {
out.println("update");
runOnUiThread(new Runnable() {
#Override
public void run() {
try {
x1display = (TextView) findViewById(R.id.x1display);
x1display.setText(in.readUTF());
} catch (IOException e) {
e.printStackTrace();
}
});
try {
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}}, 1000, 10000);//schedule the delays start/interval here
By the way, don't use printStackTrace(): Why is exception.printStackTrace() considered bad practice?