【问题标题】:java.net.SocketException: Socket is closed while socket is still openjava.net.SocketException:当套接字仍然打开时,套接字已关闭
【发布时间】:2014-09-18 08:52:29
【问题描述】:

因此,当有来自 Google Cloud Messaging (GCM) 的通知时,我正在尝试从我的服务器接收消息。我的代码如下:

public class GcmIntentService extends IntentService {
 //This class is executed by the BradcastReceiver when the devices
 //gets a message from GCM
    public static final int NOTIFICATION_ID = 1;
    private NotificationManager notificationManager;
    NotificationCompat.Builder builder;

    public GcmIntentService() {
        super("GcmIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Bundle extras = intent.getExtras();
        GoogleCloudMessaging gcm = GoogleCloudMessaging.getInstance(this);
        String messageType = gcm.getMessageType();

        if (!extras.isEmpty()) {
            if (GoogleCloudMessaging.MESSAGE_TYPE_MESSAGE.equals(messageType)) {
                Log.i("INTENTSERVICE", extras.toString());
                sendNotification(extras);
            }
            Log.e("WAKELOCK","Wakelock will end");
            GcmBroadcastReceiver.completeWakefulIntent(intent);
        }
    }

    private void sendNotification(final Bundle extras){
                Socket socket = null;
                FileOutputStream fileStream;
                MessageSet ms = null;
                try {

                    socket = new Socket(getString(R.string.server_address), 37133);
                    Tools.sendDataToServer(getApplicationContext(), 
                        socket, 
                        MessageTypes.PULLMESSAGE, 
                        extras.getString("content")); //sending does perfectly work

                    //Receive contents of Message
                    DataInputStream dis = 
                        new DataInputStream(socket.getInputStream()); // but now is doesn't 
                                                  //want to do more and the exception is thrown
                    byte type = dis.readByte();
                    /* doing things */ 
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    //Tools.close(socket);
                }

                /* post notification */
    }
}

我可以创建套接字并将数据发送到服务器,也收到了,但是当我想在电话上接收数据时,它会给出一个java.net.SocketException: Socket is closed 异常。但与此同时,服务器还在发送数据,手机上的socket也依然打开(according to debugger [PIC])。

但是为什么会出现这个错误呢?


Tools.sendDataToServer的请求码
public static void sendDataToServer(Context context, Socket socket, int messageType, String content){
        try {
            SharedPreferences prefs = context.getSharedPreferences(context.getString(R.string.SharedPrefs),0);
            OutputStream out = socket.getOutputStream();

            out.write(messageType);
            byte[] msgBytes = (prefs.getString("userID","") + "|;" + prefs.getString("userSession","") + "|;" + content).getBytes("UTF-8");
            Tools.writeDataLengthToStream(out, msgBytes.length);
            out.write(msgBytes,0,msgBytes.length);
            out.flush();
            //out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

out.close() 被注释掉时,它正在工作。这是我已经遇到的问题,但我仍然不知道为什么会这样。

【问题讨论】:

  • Tools.sendDataToServer 是做什么的?你能发布那个代码吗?
  • @eldjon :这就是代码,它可以在没有 out.close() 行的情况下工作。

标签: java android sockets exception


【解决方案1】:

至少你最终必须关闭里面的 Socket 连接实例。测试它是否为空,如果不这样做,引用可能会保留在内存中。并确保它不在主线程中执行。之后如果同样的错误仍然存​​在,请尝试重新安装应用程序以清理内存缓存。

并且还要避免关闭Tool Class里面的Socket实例。

【讨论】:

  • 测试 null 并不能阻止实例在内存中持久化。
  • Tools.close() 只是 if ! Null then close 的“快捷方式”。这不是一个好习惯吗?
【解决方案2】:

Socket 已关闭。您在此应用程序中关闭了它。对等方可能仍在尝试发送数据,但会收到“连接重置”异常。

【讨论】:

  • 是的,问题是在关闭 outputStream 后,socket 也会被关闭。但我仍然不知道为什么,因为文档并没有真正说明它。