套接字输入流在最终读取时挂起。最好的方法来处理这个?

时间:2011-02-03 12:43:15

标签: java sockets

我有点难过如何避免我的插座挂在阅读上。这是我的代码:

    Socket socket = new Socket("someMachine", 16003);
    OutputStream outputStream = socket.getOutputStream();
    InputStream inputStream = socket.getInputStream();
    try {
        outputStream.write(messageBuffer.toByteArray());
        outputStream.flush();
        BufferedReader in = new BufferedReader(new InputStreamReader(inputStream));
        StringBuffer response = new StringBuffer();
        int result;
        while ((result = in.read()) != -1) {
            response.append(Character.toChars(result));
            System.out.println(result);
        }
        System.out.println("Done!");  //never gets printed
     } catch (...) {}

上面的代码成功读取了流中的所有数据,但随后挂起。在网上阅读我希望从服务器(我无法控制)收到-1表示我已经到达流的末尾,但我得到了这个:

(Lots of data above this point)
57
10
37
37
69
79
70
10

然后挂起。所以,我的问题是:

1)我是否编码错误或服务器的响应是否存在问题?

2)如果服务器的响应存在问题(即没有返回-1),我该如何解决这个问题(即在挂起时停止读取)。

任何帮助表示赞赏!

6 个答案:

答案 0 :(得分:12)

只是停止读取会挂起的问题是这种情况可能发生在两种情况下:

1:服务器没有更多要发送的数据

2:服务器已发送更多数据,但由于网络过载,您的客户端尚未收到数据。

你只想在第一种情况下真正停止阅读,但你希望在第二种情况下读取阻止。

解决此问题的方法是制定传输协议(标准),允许服务器告诉客户端它希望发送多少数据。

如果服务器事先知道总数据大小,只需先发送传输中的总字节数,然后再发送数据。这样客户端就知道它什么时候收到了所有数据。

(或者服务器完成后可以简单地关闭连接。那样read应该会失败,但这只有在将来不需要连接时才有效。

答案 1 :(得分:5)

我认为当服务器决定停止对话时,你只会得到-1,即关闭其输出流或完全关闭套接字。此外,该流对未来潜在的传入数据保持开放。

答案 2 :(得分:2)

我不是Android专家,但这似乎在Android上运行得很好:

    try {
        telnetClient = new Socket(server, port);
    } catch (UnknownHostException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    if (telnetClient.isConnected()) {
        try {
            InputStream instr = telnetClient.getInputStream();
            int buffSize = telnetClient.getReceiveBufferSize();
            if (buffSize > 0) {
                byte[] buff = new byte[buffSize];
                int ret_read = instr.read(buff);
                screen.append(new String(buff, 0, ret_read));
            }
        } catch (IOException e) {
            screen.append("Exception while reading socket:" + e.getMessage());
        }
    }

答案 3 :(得分:2)

我刚刚遇到了同样的问题。我通过在创建套接字对象后直接设置超时来解决它...     socket.setSoTimeout(10 * 1000);

答案 4 :(得分:0)

尝试:

while ((result = in.read()) != null) {

答案 5 :(得分:0)

我发现这个问题非常强大。我试图从java执行一个Windows批处理命令,每次尝试从执行命令读取输入流时进程挂起。

我只能毫不妥协地解决这个问题。

a)通过寻找我知道会发出结束信号的特定线路        有用的信息来自流 b)或者开始一个新的线程        杀死套接字另一端的进程,在本例中为        等待一段时间后,我就是IEDriverServer.exe。

String[] cmdArray = {"cmd.exe","/c",cmd+ " 2>&1" };
    InputStream is = new ProcessBuilder(cmdArray).directory(f).start().getInputStream();

        error_buffer = new BufferedReader(new InputStreamReader(is));
        int lines=0;

        while((line=error_buffer.readLine())!=null){
            if(line.startsWith("[INFO] Final Memory: ")) {
                break;
            }

            log.debug("Reading cmd Stream "+line);
            buf.append(line);
            lines++;
        }