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?
Related
I'm trying to make a basic client <-> server connection in Java. When trying to write to the server, the client sends the details correctly, and the server stalls on reading it until the client output stream is closed. Though, once the output stream is closed it apparently closes the socket, and due to that the server can't reply to the client. Here's the main snippet of code that handles this interaction.
Client:
private void sendCmd(String cmd) {
String infoToSend = cmd;
try {
socket = new Socket(hostname, port);
System.out.println("Trying to send: " + com.sun.org.apache.xml.internal.security.utils.Base64.encode(infoToSend.getBytes()));
out = new DataOutputStream(socket.getOutputStream());
out.writeBytes(com.sun.org.apache.xml.internal.security.utils.Base64.encode(infoToSend.getBytes()));
out.flush();
System.out.println("Socket is flushed");
System.out.println("Waiting for Data");
InputStream is = socket.getInputStream();
System.out.println("Trying to get data");
BufferedReader input = new BufferedReader(
new InputStreamReader(is)
);
String line;
while((line = input.readLine()) != null) {
System.out.println(line);
}
socket.close();
} catch (IOException e) { e.printStackTrace(); }
}
Server:
public void run() {
System.out.println("Got Connection");
try {
BufferedReader in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new DataOutputStream(socket.getOutputStream());
String response;
System.out.println("Response:");
String decode = "";
while ((response = in.readLine()) != null) {
try {
decode = new String(Base64.decode(response));
} catch (Base64DecodingException e) {
e.printStackTrace();
}
}
System.out.println("Decoded: " + decode);
out.writeBytes("We got your message!");
out.flush();
out.close();
} catch (IOException e) { System.out.println("Fail"); e.printStackTrace(); }
Would anyone be able to guide me on how to fix this error. Sorry if it's super easy and I'm just unable to see it.
Sending
socket.shutdownOutput();
solved the issue.
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();
This question already has answers here:
How can I fix 'android.os.NetworkOnMainThreadException'?
(66 answers)
Closed 5 years ago.
In my application I am using TCP socket connection to connect android device to server. Socket is working normally on every device, except devices with Android 7+ where I get "Socket is closed" error.
Socket problems happen on Nexus 6P and Samsung s7!
I am using socket in Runnable in a Service, initializing socket with:
public class ClientThread implements Runnable {
public void run() {
while (true) {
try {
DataHandler.indicator.set(false);
mRun = true;
if (DataHandler.DOMAIN_IP.contains(":")) {
serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.split(":")[0]);
} else
serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.replace(":3030", ""));
Log.i("Socket", "Connecting");
socket = new Socket(serverAddr, SERVERPORT);
socket.setKeepAlive(true);
socket.setSoLinger(true, 1);
socket.setSoTimeout(30000);
DataHandler.IP_ADDRESS = socket.getLocalAddress().toString().split("/")[1];
DataInputStream dis = new DataInputStream(socket.getInputStream());
connectionDelay = MIN_WAIT;
Log.i("Socket", "Connected");
String serverMessage = "";
byte[] array = new byte[1024];
while (mRun) {
int firstbye = dis.read();
int arraylength = dis.available();
array = new byte[arraylength];
dis.read(array, 0, array.length);
String str = new String(new byte[]{(byte) firstbye});
serverMessage += str + EncodingUtils.getString(array, "UTF-8");
DataHandler.indicator.set(true);
if (firstbye != -1) {
String mstString = new String(serverMessage);
serverMessage = "";
onReceive(NotificationService.this, mstString);
} else { // if (serverMessage.equalsIgnoreCase("")) {
try {
socket.close();
Log.e("Socket", "Disconnect");
socket = null;
stopClient();
} catch (Exception e) {
e.getMessage();
}
serverMessage = null;
DataHandler.indicator.set(false);
continue;
}
}
} catch (UnknownHostException e) {
isNeedtoWrite = true;
} catch (IOException e1) {
isNeedtoWrite = true;
DataHandler.indicator.set(false);
} finally {
try {
socket.close();
DataHandler.indicator.set(false);
Log.e("Socket", "Disconnect");
socket = null;
stopClient();
} catch (Exception e) {
e.getMessage();
}
}
try {
connectionDelay = Math.min(MAX_WAIT, RandomUtils.nextInt(MIN_WAIT, (int) (connectionDelay * BACKOFF_RATE)));
Log.i("SocketSleep", String.valueOf(connectionDelay));
Thread.sleep(connectionDelay);
DataHandler.indicator.set(false);
} catch (InterruptedException e) {
e.getMessage();
}
}
}
}
Before code reaches setSoTimeout it gets to exception.
I have tried a different application which uses same Socket logic and on start it worked normally and then it just dropped unexpectedly and it doesn't work anymore. I checked on wireshark and this happens:
Does anyone have any clue what could the problem be?
Bux fix:
Due to a bug in previous versions of Android, the system did not flag writing to a TCP socket on the main thread as a strict-mode violation. Android 7.0 fixes this bug. Apps that exhibit this behavior now throw an android.os.NetworkOnMainThreadException. Generally, performing network operations on the main thread is a bad idea because these operations usually have a high latency that causes ANRs and jank.
And link to documentation.
I found out what the problem was... I actually HAD some code which called
socket.getOutputStream().write(GetSendString());
outside my thread, and this was causing socket to disconnect / crash because of NetworkOnMainthread error, but I didn't have Exception handled properly!
Maybe the problem is caused by reading the InputStream using .read command.
Try using BufferedReader, and similar for the OutputStream :
BufferedReader dis = new BufferedReader(
new InputStreamReader( socket.getInputStream() ));
PrintWriter os_buffer = new PrintWriter(
new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true);
I'm working on senior project and I'm trying to use this code to read from TCP socket but it reads from the socket once a time,but I need a continuous readings
Any hints
Thanks in advance!
This is the code:
class ClientAsyncTask extends AsyncTask<String, String, String> {
#Override
protected String doInBackground(String... params) {
String result = null;
try {
Socket socket = new Socket(params[0],
Integer.parseInt(params[1]));
InputStream is = socket.getInputStream();
PrintWriter out = new PrintWriter(socket.getOutputStream(),true);
out.println(params[2]);
BufferedReader br = new BufferedReader(
new InputStreamReader(is));
//Read data in the input buffer
result = br.readLine();
//Close the client socket
socket.close();
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return result;
}
Maybe you can use a loop for forever cycle? before you close socket with method
socket.close()
Because in official documentation:
Java doc
Once a socket has been closed, it is not available for further networking use (i.e. can't be reconnected or rebound).
I have a relatively simple program where I try establish Client Server connection and at the same time I use threads in the client side to allow for multiple connections.
I run the server and then the server invokes the client constructor and passes the port connection to the client and the thread is started on the client side.
The problem I have is that when I run the server side it doesn't want to go beyond the constructor call. It seems to get stuck at the constructor.
Sorry all this sounds a bit confusing
Any thoughts perhaps
this is the server side
ServerMultipleThreads()
{
System.out.println("Starting the server first...");
try
{
ServerSoc = new ServerSocket(7777);
listening = true;
}
catch(Exception e)
{
System.out.println(e.toString());
System.exit(1);
}
System.out.println("The server has started running");
while(listening)
{
try
{
//creating the client socket and starting the new client session
new ClientSession(ServerSoc.accept());
System.out.println("The clientSession was called");
in = new DataInputStream(clientSocket.getInputStream());
BufferedReader is = new BufferedReader(new InputStreamReader(in));
os = new PrintStream(clientSocket.getOutputStream());
while(true)
{
line = is.readLine();
PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter("myFile,txt")), true);
out.println(line);
}
}
catch(IOException ioe)
{
System.out.println(ioe.toString());
}
}
}
and this is on client side
ClientSession(Socket s)
{
clientSocket = s;
try
{
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
out.println("Welcome");
}
catch(IOException exe)
{
System.out.println(exe.toString());
}
//starting the thread
while(runner == null)
{
runner = new Thread(this);
runner.start();
}
}
public void run()
{
while(runner == Thread.currentThread())
{
BufferedReader buf = new BufferedReader(new InputStreamReader(System.in));
String stdIn;
try
{
while((stdIn = buf.readLine()) != null)
{
out.println(stdIn);
}
}
catch(IOException exe)
{
exe.toString();
}
try
{
Thread.sleep(10);
}
catch(InterruptedException e){}
}
Kind regards
Arian
That is because ServerSocket.accept() blocks until it receives a client request.
You need to have a client calling the server, something like this:
Socket socket = new Socket(host, port);
InputStream in = socket.getInputStream();
// write some data...