2

我正在使用创建一个小型服务器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()使问题消失(但作为回报,它非常慢)。所以要么我没有释放我应该释放的所有资源,要么应用程序只需要暂停..

我正在失去我所有最好的岁月。哦,顺便说一句..如果我忽略写入频道并在我接受连接后关闭,问题仍然没有消失。

4

2 回答 2

0

好吧,我发现了,所以我不妨分享一下。

我的应用需要暂停。它只是太快了,在客户端写完所有请求数据之前就关闭了连接。解决方法是继续阅读,直到收到整个 HTTP 请求。D'oh.. 吸取教训。

于 2011-02-16T21:43:43.513 回答
0

来自SocketChannel#Write 的文档(强调我的):

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

[...]

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

由您来检查 write 调用的返回值(您目前没有这样做),并发出连续的 write 调用,直到整个缓冲区都已发送。我猜是这样的:

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

如果您不写入所有响应数据然后关闭套接字,您显然会中止。

于 2015-08-05T07:40:42.270 回答