Socket not closed on Android - java

i wrote a simple TCP-client class in Java. It is used to connect to a TCP-server written in Python and handle the incoming messages in a new thread. It looks like this:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.InetSocketAddress;
import java.net.Socket;
public class TCPTestClient {
private String mHost;
private int mPort;
private Socket mSocket;
private PrintWriter mWriter;
private BufferedReader mReader;
public TCPTestClient(String host, int port) {
mHost = host;
mPort = port;
}
public void connect() throws IOException {
if (mSocket == null || mSocket.isClosed()) {
mSocket = new Socket();
mSocket.connect(new InetSocketAddress(mHost, mPort), 5000);
mWriter = new PrintWriter(mSocket.getOutputStream());
mReader = new BufferedReader(new InputStreamReader(mSocket
.getInputStream()));
new Thread(new InputHandler(mReader, this)).start();
}
}
public void close() throws IOException {
if (mSocket != null && !mSocket.isClosed()) {
mSocket.close();
}
}
class InputHandler implements Runnable {
BufferedReader mReader;
TCPTestClient mClient;
public InputHandler(BufferedReader reader, TCPTestClient client) {
mReader = reader;
mClient = client;
}
public void run() {
String line = null;
try {
while ((line = mReader.readLine()) != null) {
System.out.println(line);
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
The TCP-server simply prints "client connected" and "client disconnected" to stdout if a new client has connected or disconnected. This works great when running the TCPTestClient in a normal java-application: The connection is established when calling connect() and closed when calling close() and the waiting readLine() inside the InputHandler will fail because of a SocketException saying that the socket was closed (java.net.SocketException: Socket closed). This is the behaviour i expected.
But when i run this code on Android, the conection will not be closed: readLine() still blocks without throwing a SocketException and the server does not show the "client disconnected"-message.
Here is my activity:
import java.io.IOException;
import android.app.Activity;
import android.util.Log;
public class Foo extends Activity {
private TCPTestClient mClient;
private static final String TAG = "Foo";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.foo);
mClient = new TCPTestClient("192.168.1.2", 3456);
}
#Override
protected void onPause() {
super.onPause();
Log.d(TAG, "onPause");
try {
mClient.close();
} catch (IOException e) {
Log.d(TAG, "Disconnect failed", e);
}
}
#Override
protected void onResume() {
super.onResume();
Log.d(TAG, "onResume");
try {
mClient.connect();
} catch (IOException e) {
Log.d(TAG, "Connect failed", e);
}
}
}
So when the Activity is started/resumed, the connection will be established. And when the user clicks on the Back-Button, the connection should be closed. However, onPause() and close() is called, but the socket is not closed because the BufferedReader still blocks waiting for Input. A call like mReader.close() inside the close-method blocks, too.
Does anyone know how to fix this issue so that the connection will be closed successfully when the Activity is paused?

How have you verified that the client socket isn't closed?
The only reliable way to detect closed connections on the server side is to write data, and add heartbeats to the protocol.

Yes, pre 2.3 you have to use mSocket.shutdownInput() and mSocket.shutdownOutput() for it to throw the exception. But currently in 2.2.2, it doesn't work for me. :( Still finding a way to throw an exception.

Related

why java tcp server is accepting closed socket?

I have a class A that accepts TCP connection and send this new socket to Thread B where data from that socket is received and sent.
Class A{
Class b = new B();
public void run()
{
b.start();
while(true){
Socket socket = serverSocket.accept();
if(socket==null || socket.isClosed())continue;
b.setSocket(socket);
}
}
}
Class B extends Thread{
Socket socket;
public void setSocket(Socket p_socket) throws IOException
{
if(socket!=null && !socket.isClosed())
{
try{
socket.close();
socket = null;
Thread.sleep(5);
}
catch(Exception ex)
{}
}
socket = p_socket;
inputStream = socket.getInputStream(); // Here I am getting socket.closed() exception very much.
}
This worked fairly good in the past but now recently I am very very frequently getting the following error.
java.io.IOException: Socket Closed
at java.net.AbstractPlainSocketImpl.getInputStream(AbstractPlainSocketImpl.java:421)
at java.net.Socket$2.run(Socket.java:914)
at java.net.Socket$2.run(Socket.java:912)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.Socket.getInputStream(Socket.java:911)
I don't understand why this is happening now after years of working fine. Is this due to the network problem or Thread related something?
Updated:
Can this be the server related problem? Because the same application is running on other server but they are not having this problem.
The whole setup concept looks a bit broken. You should not "change" resources from the outside, while maybe there is still some work going on in that thread. A way better concept is to encapsulate the Socket into a new worker thread:
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class WrapHandler {
static public class Server {
private final ServerSocket mSocket;
private final ArrayList<Handler> mRunningHandlers = new ArrayList<>();
public Server(final int pPort) throws IOException {
mSocket = new ServerSocket(pPort);
new Thread(() -> mainLoop()).start();
}
private void mainLoop() {
while (true) {
try {
#SuppressWarnings("resource") final Socket socket = mSocket.accept(); // do not close, do not handle with resource, socket will be closed by handler!
final Handler h = new Handler(socket, this);
handlerStarted(h);
} catch (final IOException e) {
e.printStackTrace(); // do something useful
}
}
}
synchronized void handlerStarted(final Handler pHandler) {
mRunningHandlers.add(pHandler);
}
synchronized void handlerEnded(final Handler pHandler) {
mRunningHandlers.remove(pHandler);
}
void handleException(final Handler pHandler, final Throwable pException) {
/* again do something useful */
}
}
static public class Handler {
private final Socket mSocket;
private final Server mServer;
public Handler(final Socket pSocket, final Server pServer) {
mSocket = pSocket;
mServer = pServer;
new Thread(() -> handleSocket()).start();
}
private void handleSocket() {
try {
handleData();
} catch (final IOException e) {
mServer.handleException(this, e);
} finally {
mServer.handlerEnded(this);
stop();
}
}
private void handleData() throws IOException {
mSocket.getInputStream().read();
/* data handling code here */
}
void stop() {
try {
mSocket.close();
} catch (final IOException e) { /* ignore or handle as you will */ }
}
}
}

Sending messages to clients TCP connection fails with an nullpointexception [duplicate]

This question already has answers here:
What is a NullPointerException, and how do I fix it?
(12 answers)
Closed 6 years ago.
Hi all :) Sorry for this really long question but this needs some explaination.
I was given an assignment where i have to turn a very simple game into a 2 player multiplayer game. The reason why we have to make this game is to learn more about threads and concurrency. I have never worked with concurrency nor with multiple threads.
My idea is to create a TCP server like i have done in GameServer.java where i create a new ServiceObject for each player. I create a thread for each ServiceObject where i will recieve, handle and send commands from a client.
Gameserver.java
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
public class GameServer {
public static void main(String[] args) throws IOException {
ServerSocket server = new ServerSocket(6789);
System.out.println("Waiting for clients to connect . . . ");
Socket s1 = server.accept();
System.out.println("Clients connected.");
PlayerService servicep1 = new PlayerService(s1);
Thread t1 = new Thread(servicep1);
Socket s2 = server.accept();
System.out.println("Clients connected.");
PlayerService servicep2 = new PlayerService(s2);
Thread t2 = new Thread(servicep2);
t1.start();
t2.start();
servicep1.sendDataToClient("ready");
servicep2.sendDataToClient("ready");
}
}
PlayerService.java
package server;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Scanner;
import java.util.concurrent.LinkedBlockingQueue;
import game2016.Player;
public class PlayerService extends Thread {
private Socket s;
private PlayerService opponent;
private Scanner in;
private PrintWriter out;
public PlayerService(Socket aSocket) {
this.s = aSocket;
}
public void setOpponent(PlayerService opponent) {
this.opponent = opponent;
}
public void run() {
try {
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
try {
doService();
} finally {
// s.close();
}
} catch (IOException exception) {
exception.printStackTrace();
}
}
public void doService() throws IOException {
while (true) {
if (!in.hasNext()) {
return;
}
String command = in.next();
if (command.equals("QUIT")) {
return;
} else
recieveFromClient(command);
}
}
public void recieveFromClient(String command) throws IOException {
System.out.println(command);
if(command.equals("player")) {
String newPlayerName = in.next();
int xPos = in.nextInt();
int yPos = in.nextInt();
String direction = in.next();
// sendDataToOpponent("addOpponent " + newPlayerName + " " + xPos + " " + yPos + " " + direction);
}
}
public void sendDataToClient(String response) {
out.write(response + "\n");
out.flush();
}
public void sendDataToOpponent(String response) {
opponent.sendDataToClient(response);
}
}
To send data from one client to another client i have a reference to the opponents servicelayer as i can invoke the sendDataToOpponent() method to send data to him and if the server have to communicate i can just invoke sendDataToClient() from the server.
My problem is that i want to postpone opening my clients GUI to both clients have connected.
Main.java(Client) - GUI code have been left out
private static Socket s;
private static InputStream instream;
private static OutputStream outstream;
private static Scanner in;
private static PrintWriter out;
private static boolean isOpponentConnected;
public static void main(String[] args) throws Exception {
openConnection();
reciever();
waitOpponentConected();
launch(args);
}
public static void waitOpponentConected() throws Exception {
while(!isOpponentConnected) {
System.out.println("Waiting for opponent");
Thread.sleep(2000);
}
System.out.println("Opponent is ready now");
}
public static void openConnection() throws IOException {
s = new Socket("localhost", 6789);
System.out.println("Connection established");
instream = s.getInputStream();
outstream = s.getOutputStream();
in = new Scanner(instream);
out = new PrintWriter(outstream);
}
public static void responseFromServer() throws IOException {
try {
while(in.hasNext()) {
String response = in.next();
if(response.equals("ready")) {
isOpponentConnected = true;
System.out.println("Ready");
}
}
} catch (Exception e) {
}
}
public static void reciever() {
Task<Void> task = new Task<Void>() {
#Override
protected Void call() throws Exception {
while(true) {
responseFromServer();
}
}
};
new Thread(task).start();
}
public static void sendCommandToServer(String command) throws IOException {
out.print(command + "\n");
out.flush();
}
I've created a Thread to recieve commands from the server, and when both clients have connected to the server it sends a string 'ready' to each of the clients. My thought was that The Main-thread sleeps till isOpponentConnected is true.
But my gameserver fails and prints out a nullpointer exception when the second clients connects to the server. I've spend to days reading and trying to fix this bug. When i run the code in debug mode, both clients recieves the ready signal and the GUI starts for both clients.
Exception in thread "main" java.lang.NullPointerException
at server.PlayerService.sendDataToClient(PlayerService.java:67)
at server.GameServer.main(GameServer.java:23)
Can you guys see anything i'm obviously doing wrong?
I think this queston is interesseting because it's not just the nullpointerexception, it's about structering TCP server-client relationships and the chain when things are initialized and ready when threads and connections are made.
It should be fixable from inside the PlayerService.java class you have posted.
I suggest moving:
in = new Scanner(s.getInputStream());
out = new PrintWriter(s.getOutputStream());
from public void run() to your PlayerService constructor:public PlayerService(Socket aSocket)
It looks like the function sendDataToClient is trying to use the out variable before it gets initialised.

Cannot receive a value on Raspberry pi 3 from Android via Bluetooth

I am new to Programming with Java, and I am trying to send some value from 'Blueterm' application on Android and receive it on my Raspberry pi 3 via Bluetooth. Already raspberrypi3 has built in bluetooth and I am able to pair the 2 devices but I am not able to connect them and don't know how to start with the Java code. I hava tried ConnectedThread and AcceptThread but no progress, so if anyone could help me with this.
import java.io.IOException;
import java.io.InputStream;
import java.util.*;
import java.util.UUID;
import javax.bluetooth.*;
import android.bluetooth.*;
public class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;
private UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
public AcceptThread() {
BluetoothAdapter Badp= BluetoothAdapter.getDefaultAdapter();
if (Badp == null) {
// Device does not support Bluetooth
System.out.println("Bluetooth Not Supported");
}
// Use a temporary object that is later assigned to mmServerSocket,
// because mmServerSocket is final
BluetoothServerSocket tmp = null;
try {
// MY_UUID is the app's UUID string, also used by the client code
tmp = Badp.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) { }
mmServerSocket = tmp;
}
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned
while (true) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
break;
}
// If a connection was accepted
if (socket != null) {
// Do work to manage the connection (in a separate thread)
manageConnectedSocket(socket);
try {
mmServerSocket.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
break;
}
}
}
/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
try {
mmServerSocket.close();
} catch (IOException e) { }
}
private void manageConnectedSocket(BluetoothSocket socket) {
//acceptThread.cancel();
}
}

NullPointerException in Thread's run method

I would really appreciate help with my program. It is some sort of chat server with multiple clients.
Here's the server code:
package com.server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
public class Server {
public static int PORT;
private ServerSocket server;
private Socket socket;
public Server(int port) throws IOException {
PORT = port;
server = new ServerSocket(PORT);
System.out.println("server started");
try {
while (true) {
socket = server.accept();
try {
new ServeClient(socket);
} catch (IOException e) {
socket.close();
}
}
} finally {
server.close();
}
}
public static void main(String[] args) throws IOException {
int port = Integer.parseInt(args[0]);
Server server = new Server(port);
}
}
I start the server and then create a Client. The server receives connection socket from socket
and creates a ServeClient Thread.
Here's ServeClient code:
package com.server;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;
import java.util.Enumeration;
import java.util.Vector;
import com.gui.WindowManager;
public class ServeClient extends Thread {
private final Socket socket;
private BufferedReader in;
private PrintWriter out;
private String msg;
public static final String ENDSTRING = "END";
public static Vector clients = new Vector();
public ServeClient(final Socket socket) throws IOException {
this.socket = socket;
System.out.println("socket " + socket);
in = new BufferedReader(new InputStreamReader(socket.getInputStream()));
out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(
socket.getOutputStream())), true);
start();
}
public void run() {
try {
clients.add(this);
while (true) {
msg = in.readLine();
if (msg == ENDSTRING)
break;
broadcast(msg);
}
System.out.println("closing...");
} catch (IOException e) {
System.err.println("IO EXCEPTION");
} finally {
try {
socket.close();
} catch (IOException e) {
System.err.println("SOCKET NOT CLOSED");
}
}
}
#SuppressWarnings("deprecation")
public void broadcast(String msg) {
synchronized (clients) {
Enumeration<ServeClient> e = clients.elements();
while (e.hasMoreElements()) {
ServeClient serveClient = e.nextElement();
try {
synchronized (serveClient.out) {
serveClient.out.println(msg);
}
} catch (Exception eee) {
serveClient.stop();
}
}
}
}
}
What i get is a NullPointerException when ServeClient invokes run() method
server started
socket Socket[addr=/127.0.0.1,port=51438,localport=8888]
Exception in thread "Thread-0" java.lang.NullPointerException
at com.server.ServeClient.run(ServeClient.java:33)
line 33 is the line with first "try" statement in ServeClient run() method
com.server.ServeClient.run(ServeClient.java:33)
I don't believe that it's happening at the try.
Open up an IDE, turn on debugging, and step through until you can see what's happening. That's the fastest way to figure out what you've missed.
There's an object that you're assuming is fine that is not. Find it.
Here's an example of how to do this properly:
http://www.kodejava.org/examples/216.html
Your problem is with the order in which static instance variables are initialised. Try doing something like:
...
private static Vector clients = null;
...
if (clients==null) {
clients = new Vector(); // consider putting this in a synchronized block
}
before you add the client to the vector.
Sorry for necroing such an old issue but it seemed like this problem wasn't resolved, so I'll give a bit of input from my end.
I've had a similar problem and the compiler also kept telling me that the problem was at the start() method. However, when I commented out the thread part and just ran the code on the same thread as the UI, the compiler directed me to the real source of the problem: the code inside the thread.
After making sure the code didn't give an error, I enclosed the code with the original thread code, and it stopped giving me the NullPointerException error.
Hope this helps someone along the way.
Remove the duplicate class declaration in JPanel.
I was trying to run a timer thread that updated a clock in the main application window.
I had created the JFrame with Eclipse/WindowBuilder and had followed a tutorial on how to make a timer. I had copied the declaration of the textfield into the class declaration to make it available for the entire class, but forgot to remove the Class Id in front of the widget definition. So it still initialized the local instance and not the global one. Thus when I accessed the global one it was still null.

Async Tcp Connection

I have a slight problem, I have a TCP class which connects to a server, transfers data then closes, this all works well except for if I connect, then stop it, it works, if I keep on doing this, it works, but on the fifth time the connection hangs without any error and doesn't transfer any data.. I've got no idea how to fix this... This is my TCP class code:
package com.millennium.isynccrm.Classes;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;
import java.net.UnknownHostException;
import android.os.AsyncTask;
import android.os.CountDownTimer;
import android.util.Log;
public class TcpClient {
public static boolean connected = false;
private static Socket socket;
private static boolean pause = false;
private static SyncClient syncClient = new SyncClient();
public static int sendCount = 0;
public static int receiveCount = 0;
private static AsyncTask<?, ?, ?> sendAsyncTask;
private static AsyncTask<?, ?, ?> receiveAsyncTask;
public TcpClient() { }
public void send (String line) {
if (!connected) connect();
while (!connected) { }
sendAsyncTask = new SenderThread().execute(line);
}
public void disconnect() {
try {
if(connected == true) {
socket.close();
connected = false;
sendCount = 0;
receiveCount = 0;
if (receiveAsyncTask.getStatus().name().equals("RUNNING")) {
receiveAsyncTask.cancel(true);
}
if (sendAsyncTask.getStatus().name().equals("RUNNING")) {
sendAsyncTask.cancel(true);
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
public void pauseReceivingForTimeInterval(int milliseconds) {
pause = true;
new CountDownTimer(milliseconds, 0) {
public void onTick(long millisUntilFinished) { }
public void onFinish() {
pause = false;
}
}.start();
}
private void connect() {
new Thread(new Runnable() {
public void run() {
try {
if (connected == false) {
socket = new Socket("192.168.1.1", 80);
connected = true;
sendCount = 0;
receiveCount = 0;
try {
if (receiveAsyncTask.getStatus().name().equals("FINISHED")) {
receiveAsyncTask = new RecieverThread().execute("");
} else if (receiveAsyncTask.getStatus().name().equals("RUNNING")) {
receiveAsyncTask.cancel(true);
receiveAsyncTask = new RecieverThread().execute("");
}
} catch (Exception e) { receiveAsyncTask = new RecieverThread().execute(""); }
}
} catch (UnknownHostException e) {
connected = false;
e.printStackTrace();
} catch (IOException e) {
connected = false;
e.printStackTrace();
}
}
}).start();
}
private static PrintWriter output;
private static BufferedReader input = null;
private class RecieverThread extends AsyncTask<String, Void, String> {
protected String doInBackground(String... line) {
while (pause) { }
try {
receiveCount++;
if (receiveCount == 1) input = new BufferedReader(new InputStreamReader(socket.getInputStream()), 8 * 1024);
return input.readLine();
} catch (IOException e) {
Log.d("error", "stop");
}
return "stop";
}
protected void onPostExecute(String result) {
if (result == null) return;
else if (!result.equals("") && !result.equals("stop")) syncClient.recieveMessage(result);
else if (!result.equals("stop")) receiveAsyncTask = new RecieverThread().execute("");
}
}
private class SenderThread extends AsyncTask<String, Void, String> {
protected String doInBackground(String... line) {
while (pause) { }
sendCount++;
if (sendCount == 1) {
try {
output = new PrintWriter(socket.getOutputStream(),true);
} catch(Exception e) { e.printStackTrace(); }
}
String msg = line[0] + "\r\n";
output.print(msg);
output.flush();
return "";
}
protected void onPostExecute(String result) {
}
}
}
As you can see another class sends a line to this class to send to the server, then a Async task sends it and another Async task receives it and passes it onto another class which processes it and so on. On the UI I have a start button which when is pressed turns into a stop button and when stop is pressed it calls the 'disconnect' function in here.
I'm not too sure wherever I have done my RecieverThread AsyncTask is correct, it waits for a line from the socket then passes it on and restarts it self to listen for another line, is this a 'good' way of doing this? Or is it a terrible way (which I imagine it is). To be honest I think this class is very 'messy' and I will more than likely be redoing it.
Any suggestion why I can never send data on the fifth time I connect to the server? (One last note, the server is not to blame here, as we have a iPhone app which does the same thing) (Extra side note.. I'm pretty new to Tcp connections and that sort of stuff, and new to Threading/Async Tasks.) :)
Any help, assistance would be much appreciated (: Thanks!
while (!connected) {}??? that's no way to do asynchronous anything. You are hogging the CPU waiting for something to happen, and preventing it from happening by hogging the CPU. Use a Selector, or do a blocking-mode connect.

Categories

Resources