Я написал простой класс TCP-клиента на Java. Он используется для подключения к TCP-серверу, написанному на Python, и обработки входящих сообщений в новом потоке. Это выглядит так:
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();
}
}
}
}
TCP-сервер просто печатает «клиент подключен» и «клиент отключен» в стандартный вывод, если новый клиент подключился или отключился. Это прекрасно работает при запуске TCPTestClient в обычном java-приложении: соединение устанавливается при вызове connect () и закрывается при вызове close (), а ожидание readLine () внутри InputHandler завершится сбоем из-за SocketException, говорящего о том, что сокет был закрыто (java.net.SocketException: Socket closed
). Это поведение, которое я ожидал.
Но когда я запускаю этот код на Android, соединение не будет закрыто: readLine () по-прежнему блокируется, не выдавая SocketException, и сервер не показывает сообщение "клиент отключен".
Вот моя деятельность:
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);
}
}
}
Таким образом, когда действие будет запущено / возобновлено, соединение будет установлено. И когда пользователь нажимает кнопку «Назад», соединение должно быть закрыто. Однако onPause () и close () вызывается, но сокет не закрывается, потому что BufferedReader все еще блокирует ожидание ввода. Вызов, подобный mReader.close()
, также внутри блоков close-метода.
Кто-нибудь знает, как решить эту проблему, чтобы соединение было успешно закрыто после приостановки действия?