【问题标题】:Android SocketException 'Socket is closed' closed even after socket.isClosed() is used即使在使用 socket.isClosed() 之后,Android SocketException 'Socket is closed' 也会关闭
【发布时间】:2014-06-28 08:35:48
【问题描述】:

我有一个应用程序,我在其中使用套接字来侦听来自服务器的消息,它有两个活动,每个活动都有自己的方法来处理消息。

当我从第一个开始第二个时,我关闭该活动的套接字侦听器并在第二个活动onCreate 方法中启动一个新的。但是,当我切换活动时,我收到 java.net.SocketException: Socket is closed 错误。

public synchronized void run(){
    //Check if the thread has been shut down
    while(!this.stopped){
        socket = null;
        try{
            //Socket
            socket = new DatagramSocket(port);
            //Packet
            byte[] data = new byte [1024];
            DatagramPacket packet = new DatagramPacket(data, data.length);
            if(!socket.isClosed()){
                //Store data from socket into packet
                socket.receive(packet);
                //Create a string from the data
                String received = new String(packet.getData(),packet.getOffset(),packet.getLength());

                //Log the string TODO remove this
                Log.i("RECEIVED", received);

                //Get a new message object from the handler
                Message msg = commandHandler.obtainMessage();
                //Store the string in the message
                msg.obj = received;
                //Send the message to the handler
                commandHandler.sendMessage(msg);
            }

        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(socket != null)
                socket.close();
        }
    }
}

/**
 * Close the listener
 */
public void shutDown(){
    this.stopped = true;
    if(socket != null){
        socket.close();
    }
}

从上面可以看到,我使用!socket.isClosed()在收到消息前检查socket是否关闭

错误跟踪:

06-27 19:48:12.129: W/System.err(19460): java.net.SocketException: Socket closed
06-27 19:48:12.129: W/System.err(19460):    at libcore.io.Posix.recvfromBytes(Native Method)
06-27 19:48:12.129: W/System.err(19460):    at libcore.io.Posix.recvfrom(Posix.java:136)
06-27 19:48:12.129: W/System.err(19460):    at libcore.io.BlockGuardOs.recvfrom(BlockGuardOs.java:164)
06-27 19:48:12.129: W/System.err(19460):    at libcore.io.IoBridge.recvfrom(IoBridge.java:513)
06-27 19:48:12.129: W/System.err(19460):    at java.net.PlainDatagramSocketImpl.doRecv(PlainDatagramSocketImpl.java:161)
06-27 19:48:12.129: W/System.err(19460):    at java.net.PlainDatagramSocketImpl.receive(PlainDatagramSocketImpl.java:169)
06-27 19:48:12.129: W/System.err(19460):    at java.net.DatagramSocket.receive(DatagramSocket.java:253)
06-27 19:48:12.129: W/System.err(19460):    at com.android.homeservice.server.TabletListener.run(TabletListener.java:54)

更新

所以事实证明,我在第二个活动中调用了线程的 start() 方法两次,一次是在 onCreate 中,另一次是在 onStart 中,这是代码的先前版本遗留下来的。无论如何,谢谢你的所有回答,如果我浪费了你的时间,对不起

【问题讨论】:

  • 套接字实际上可以在检查它是否关闭后关闭,例如在等待接收数据时。您何时何地调用 socket.close()?
  • 我在创建启动新活动的意图之前调用了 shutDown() 方法,以尝试关闭以前的监听器

标签: java android sockets socketexception


【解决方案1】:

我建议重新架构。将套接字处理全部保留在线程上,并告诉线程何时应该退出。当线程退出时,关闭套接字。

public synchronized void run(){
    //Check if the thread has been shut down
    Socket socket = new DatagramSocket(port);
    while(!this.stopped){
        socket = null;
        try{
            //Socket
            //Packet
            byte[] data = new byte [1024];
                //Store data from socket into packet
                socket.receive(packet);
                //Create a string from the data
                String received = new String(packet.getData(),packet.getOffset(),packet.getLength());

                //Log the string TODO remove this
                Log.i("RECEIVED", received);

                //Get a new message object from the handler
                Message msg = commandHandler.obtainMessage();
                //Store the string in the message
                msg.obj = received;
                //Send the message to the handler
                commandHandler.sendMessage(msg);
            }

        }catch (IOException e) {
            e.printStackTrace();
        }finally{
            if(socket != null)
                socket.close();
        }
    }
    socket.close()
}

/**
 * Close the listener
 */
public void shutDown(){
    this.stopped = true;

}

【讨论】:

  • DatagramSocket.receive() 块。
【解决方案2】:

显然其他人在 isClosed() 测试和引发异常的行之间关闭了它。

让'socket'成为一个局部变量,然后没有其他人可以关闭它。

但是,每次在循环周围创建一个套接字一开始就完全没有意义。只需在线程的生命周期内使用相同的套接字。如果您从未在循环内关闭它,则它不可能抛出该异常,并且您永远不需要对其进行测试。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-04-14
    • 2019-03-20
    • 2011-10-11
    • 1970-01-01
    • 2013-09-05
    • 1970-01-01
    • 1970-01-01
    • 2022-10-12
    相关资源
    最近更新 更多