【问题标题】:Socket not closed on AndroidAndroid上的套接字未关闭
【发布时间】:2011-08-20 16:41:08
【问题描述】:

我用 Java 编写了一个简单的 TCP 客户端类。它用于连接到用 Python 编写的 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 服务器仅将“客户端连接”和“客户端断开连接”打印到标准输出。这在普通 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);
        }
    }
}

所以当Activity启动/恢复时,连接就会建立。当用户点击后退按钮时,连接应该被关闭。然而,onPause() 和 close() 被调用,但是套接字并没有关闭,因为 BufferedReader 仍然阻塞等待输入。像 mReader.close() 这样的调用也在 close-method 块中。

有谁知道如何解决这个问题,以便在 Activity 暂停时成功关闭连接?

【问题讨论】:

  • 好的,我想我找到了解决方案 :-) 现在我在关闭方法中调用 mSocket.shutdownInput()mSocket.shutdownOutput()。这会导致 readLine() 返回并且我的 InputHandler-Thread 退出并且服务器打印“断开连接”消息。
  • 您只需要 shutdownInput() 即可。

标签: java android android-activity tcp bufferedreader


【解决方案1】:

是的,在 2.3 之前,您必须使用 mSocket.shutdownInput() 和 mSocket.shutdownOutput() 才能抛出异常。但目前在 2.2.2 中,它对我不起作用。 :( 仍在寻找抛出异常的方法。

【讨论】:

  • 你解决过这个问题吗?我遇到了类似的问题,不得不将minSdkVersion 提高到9,因为我不知道如何让它在 Froyo 及以下... :/
【解决方案2】:

您如何验证客户端套接字未关闭?

在服务器端检测关闭连接的唯一可靠方法是写入数据,并向协议添加心跳。

【讨论】:

  • 正如我所写:服务器将向标准输出打印“客户端断开连接”消息。此外,InputHandler-Thread 应该终止,但它仍然挂在 readLine() 上。所以也许只有流没有正确关闭。这就是我想要的:) 我认为当 InputStream 关​​闭时,服务器会看到这个并打印预期的消息。但我不知道如何关闭流,因为如前所述,mReader.close() 也会阻塞。编辑:并且使用“普通Java”它可以按预期工作;)
猜你喜欢
  • 1970-01-01
  • 2015-12-09
  • 1970-01-01
  • 2017-07-18
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 2014-02-04
  • 2018-12-14
相关资源
最近更新 更多