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?
mSocket.shutdownInput()andmSocket.shutdownOutput()in my close-method. This causes the readLine() to return and my InputHandler-Thread to exit and the server prints the "disconnected"-message. - Biggie