我用Java編寫了一個簡單的TCP客戶端類。它用於連接到用Python編寫的TCP服務器,並在新線程中處理傳入的消息。它看起來像這樣:Android上的套接字未關閉
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服務器簡單地打印「連接的客戶端」和「客戶端斷開連接」到標準輸出,如果一個新的客戶端已連接或斷開。在正常的java應用程序中運行TCPTestClient時,這很好用:連接在調用connect()時建立,在調用close()時關閉,InputHandler內的等待readLine()將因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仍然阻塞等待輸入,因此套接字未關閉。在close-method塊內也可以調用mReader.close()
。
有誰知道如何解決此問題,以便連接將在活動暫停時成功關閉?
OK,我想我找到:-)現在我打電話\t \t \t'mSocket.shutdownInput()在我的特寫解決方案'和'mSocket.shutdownOutput()'方法。這會導致readLine()返回,並且我的InputHandler-Thread將退出,並且服務器將打印「已斷開」的消息。 – Biggie 2011-05-07 11:40:43
你只需要shutdownInput()。 – EJP 2014-04-29 08:43:11