자바에서 간단한 TCP 클라이언트 클래스를 작성했습니다. 이것은 파이썬으로 작성된 TCP 서버에 연결하고 들어오는 메시지를 새로운 스레드에서 처리하는 데 사용됩니다. 그것은 다음과 같습니다안드로이드에서 소켓이 닫히지 않았습니다.
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 서버는 단순히 새로운 클라이언트가 연결되거나 연결이 끊어진 경우 stdout에 "연결된 클라이언트"와 "클라이언트 연결을"인쇄합니다. 이것은 정상적인 자바 응용 프로그램에서 TCPTestClient를 실행할 때 훌륭하게 작동합니다. connect()를 호출 할 때 연결이 설정되고 close()를 호출 할 때 연결이 닫히고 InputHandler 내부에서 대기중인 readLine()은 소켓이 마감 (java.net.SocketException: Socket closed
). 이것은 내가 예상 한 행동입니다.
그러나 Android에서이 코드를 실행하면 conection이 닫히지 않습니다. readLine()은 SocketException을 throw하지 않고 계속 차단하고 서버는 "클라이언트 연결이 끊김"메시지를 표시하지 않습니다. 활동이 시작될 때
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()
과 같은 호출도 있습니다.
활동이 일시 중지되었을 때 연결이 성공적으로 닫히도록이 문제를 해결하는 방법을 아는 사람이 있습니까?
을, 나는 내 닫기 -에서 지금은 \t \t \t'mSocket.shutdownInput을 (전화 :-) 솔루션)'와'mSocket.shutdownOutput을()'찾은 것 같아요 방법. 이로 인해 readLine()이 반환되고 InputHandler-Thread가 종료되고 서버는 "disconnected"메시지를 인쇄합니다. – Biggie
그 경우에는 shutdownInput() 만 필요합니다. – EJP