当服务器死后,从SocketChannel读取会给我一个StackOverflowError [重复]

问题描述 投票:-1回答:1

此问题已经在这里有了答案:

我正在用Java编写一个TCP客户端,该客户端将从服务器接收请求并对其进行响应,如果在最近一分钟内服务器未发送ping命令,则重新连接到服务器。客户端是同步的,所有内容都在一个线程上运行。每当我强行关闭服务器时(这对客户端来说是意外的,但是TCP不会超时而不是立即知道服务器已关闭吗?),即使我已经封闭了,我也会立即在SocketChannel.read上收到StackOverflowError。尝试一下。

以下是相关代码:

 private void readRequestHeader() {
        if (requestHeaderBuffer == null) {
            requestHeaderBuffer = ByteBuffer.allocate(9);
        }
        try {
            socketChannel.read(requestHeaderBuffer); //LINE 52: ERROR!
        } catch (Exception e) {
        }
        if (lastPingTime != 0 && System.currentTimeMillis() > lastPingTime + pingInterval * 2) {
            disconnect();
        } else {
            if (requestHeaderBuffer.hasRemaining()) {
                readRequestHeader();
            } else {
                BinaryBufferReader requestHeader = new BinaryBufferReader(requestHeaderBuffer.array()); //LINE 61: MORE ERROR!
                requestPing = requestHeader.readBool();
                requestIndex = requestHeader.readInt();
                requestDataLength = requestHeader.readInt();
                if (requestPing) {
                    lastPingTime = System.currentTimeMillis();
                }
                requestDataBuffer = null;
                readRequestData();
            }
        }
    }

这是LogCat的输出:

10-31 13:41:34.385  3687  9289 E AndroidRuntime: FATAL EXCEPTION: Thread-2
10-31 13:41:34.385  3687  9289 E AndroidRuntime: Process: com.test.test, PID: 3687
10-31 13:41:34.385  3687  9289 E AndroidRuntime: java.lang.StackOverflowError: stack size 1037KB
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at java.lang.ThreadLocal$ThreadLocalMap.getEntry(ThreadLocal.java:416)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at java.lang.ThreadLocal$ThreadLocalMap.-wrap0(Unknown Source:0)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at java.lang.ThreadLocal.get(ThreadLocal.java:163)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at dalvik.system.BlockGuard.getThreadPolicy(BlockGuard.java:145)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:42)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:223)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at sun.nio.ch.IOUtil.read(IOUtil.java:197)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:419)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at com.test.test.Client.readRequestHeader(Client.java:52)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at com.test.test.Client.readRequestHeader(Client.java:61)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at com.test.test.Client.readRequestHeader(Client.java:61)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at com.test.test.Client.readRequestHeader(Client.java:61)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at com.test.test.Client.readRequestHeader(Client.java:61)
10-31 13:41:34.385  3687  9289 E AndroidRuntime:    at com.test.test.Client.readRequestHeader(Client.java:61)

这是整个客户端类代码:

package com.test.test;

import android.app.Service;

import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;

class Client {
    public Service service;
    private SocketChannel socketChannel;
    private int pingInterval;
    private long lastPingTime;
    private ByteBuffer requestHeaderBuffer;
    private ByteBuffer requestDataBuffer;
    private ByteBuffer responseHeaderBuffer;
    private ByteBuffer responseDataBuffer;
    private boolean requestPing;
    private int requestIndex;
    private int requestDataLength;

    public Client(Service service) {
        this.service = service;
        try {
            socketChannel = SocketChannel.open();
        } catch (Exception e) {
        }
        pingInterval = 30000;
        connect();
    }

    private void connect() {

        try {
            socketChannel.connect(new InetSocketAddress("0.tcp.ngrok.io", 14081));
        } catch (Exception e) {
        }
        lastPingTime = 0;
        requestHeaderBuffer = null;
        readRequestHeader();
    }

    public void disconnect() {
        connect();
    }

    private void readRequestHeader() {
        if (requestHeaderBuffer == null) {
            requestHeaderBuffer = ByteBuffer.allocate(9);
        }
        try {
            socketChannel.read(requestHeaderBuffer); \\LINE 52: ERROR!
        } catch (Exception e) {
        }
        if (lastPingTime != 0 && System.currentTimeMillis() > lastPingTime + pingInterval * 2) {
            disconnect();
        } else {
            if (requestHeaderBuffer.hasRemaining()) {
                readRequestHeader();
            } else {
                BinaryBufferReader requestHeader = new BinaryBufferReader(requestHeaderBuffer.array()); \\LINE 61: MORE ERROR!
                requestPing = requestHeader.readBool();
                requestIndex = requestHeader.readInt();
                requestDataLength = requestHeader.readInt();
                if (requestPing) {
                    lastPingTime = System.currentTimeMillis();
                }
                requestDataBuffer = null;
                readRequestData();
            }
        }
    }

    private void readRequestData() {
        if (requestDataBuffer == null) {
            requestDataBuffer = ByteBuffer.allocate(requestDataLength);
        }
        try {
            socketChannel.read(requestDataBuffer);
        } catch (Exception e) {
        }
        if (lastPingTime != 0 && System.currentTimeMillis() > lastPingTime + pingInterval * 2) {
            disconnect();
        } else {
            if (requestDataBuffer.hasRemaining()) {
                readRequestHeader();
            } else {
                BinaryBufferReader requestData = new BinaryBufferReader(requestDataBuffer.array());
                BinaryBufferWriter responseHeader = new BinaryBufferWriter();
                BinaryBufferWriter responseData = new BinaryBufferWriter();
                if (requestPing) {
                    responseData.writeString("ping");
                } else {
                    String requestAction = requestData.readString();
                    if (requestAction.equals("hello")) {
                        ActionHello.run(this, requestData, responseData);
                    } else if (requestAction.equals("update")) {
                        ActionUpdate.run(this, requestData, responseData);
                    } else {
                        responseData.writeString("blah");
                    }
                }
                byte[] temp = responseData.getBuffer();
                responseHeader.writeBool(requestPing);
                responseHeader.writeInt(requestIndex);
                responseHeader.writeInt(temp.length);
                responseHeaderBuffer = ByteBuffer.wrap(responseHeader.getBuffer());
                responseDataBuffer = ByteBuffer.wrap(temp);
                writeResponseHeader();
            }
        }
    }

    private void writeResponseHeader() {
        while (responseHeaderBuffer.hasRemaining()) {
            try {
                socketChannel.write(responseHeaderBuffer);
            } catch (Exception e) {
            }
        }
        if (lastPingTime != 0 && System.currentTimeMillis() > lastPingTime + pingInterval * 2) {
            disconnect();
        } else {
            if (responseHeaderBuffer.hasRemaining()) {
                writeResponseHeader();
            } else {
                writeResponseData();
            }
        }
    }

    private void writeResponseData() {
        while (responseDataBuffer.hasRemaining()) {
            try {
                socketChannel.write(responseDataBuffer);
            } catch (Exception e) {
            }
        }
        if (lastPingTime != 0 && System.currentTimeMillis() > lastPingTime + pingInterval * 2) {
            disconnect();
        } else {
            if (responseDataBuffer.hasRemaining()) {
                writeResponseData();
            } else {
                requestHeaderBuffer = null;
                readRequestHeader();
            }
        }
    }
}
java sockets stack-overflow
1个回答
0
投票

不要默默地吞下例外

catch (Exception e) {
}

我想这将是记录消息的好地方,return

否则,at com.test.test.Client.readRequestHeader(Client.java:61)继续被调用导致StackOverflow

© www.soinside.com 2019 - 2024. All rights reserved.