apr_socket_recv:已建立的连接已被主机中的软件中止

时间:2011-02-15 21:43:31

标签: java nio apachebench

我正在使用java.nio创建一个小型服务器,但在尝试对其进行压力测试时,我不断收到有关在服务器端重置连接的消息,或者更具体地说:

apr_socket_recv: An established connection was aborted by the software in your host machine

我试图将其缩小到最简单的循环,但仍然没有运气。我可以在一百个左右的连接之后得到错误,或者可能只是在1或2之后。

这是服务器循环:

byte[] response = ("HTTP/1.1 200 OK\r\n"
            + "Server: TestServer\r\n"
            + "Content-Type: text/html\r\n"
            + "\r\n"
            + "<html><b>Hello</b></html>").getBytes();

        SocketChannel newChannel = null;
        while (active) {
            try {
                //get a new connection and delegate it.
                System.out.print("Waiting for connection..");
                newChannel = serverSocketChannel.accept();
                System.out.println("ok");

                newChannel.configureBlocking(true);
                newChannel.write(ByteBuffer.wrap(response));
            }
            catch (IOException e) {
                e.printStackTrace();
            }
            finally {
                try {
                    newChannel.close();
                } catch (IOException ex) {
                    Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
                }
            }

        }

我已经尝试检查写入是否没有写入所有请求的字节,但看起来确实如此。有趣的是,在每个System.gc()之后调用newChannel.close()会使问题消失(但作为回报,它的速度非常慢)。所以要么我不释放我应该发布的所有资源,要么应用程序只需要暂停..

我在这方面失去了所有最好的岁月。哦,顺便说一句..如果我忽略写入通道并在接受连接后关闭,问题仍然不会消失。

2 个答案:

答案 0 :(得分:0)

我发现了它,所以我不妨分享它。

我的应用需要暂停。它只是过快,并在客户端编写了所有请求数据之前关闭了连接。修复将继续阅读,直到收到整个HTTP请求。噢噢......上课了。

答案 1 :(得分:0)

来自the docs for SocketChannel#Write(强调我的):

  

尝试将 r 字节写入通道,其中 r 是   缓冲区中剩余的字节数,即src.remaining(),   此时调用此方法。

     

[...]

     

返回: 写入的字节数,可能为零

由您来检查写入调用的返回值(您当前没有这样做),并发出连续的写入调用,直到整个缓冲区已被发送。我想是这样的事情:

ByteBuffer toWrite = ByteBuffer.wrap(response);
while (toWrite.remaining() > 0) {
    newChannel.write(toWrite);
}

如果您没有写完所有的响应数据然后关闭套接字,那么您很明显会中止。