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

发布于 2024-10-17 16:53:24 字数 1552 浏览 0 评论 0原文

我正在使用 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);
                }
            }

        }

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

我正在为此失去所有最好的时光。哦,顺便说一句......如果我忽略对通道的写入并在接受连接后关闭,问题仍然不会消失。

I'm creating a small server using java.nio, but when trying to stress test it I keep getting messages about the connection being reset on the server side, or more specifically:

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

I've tried to narrow it down to the most simple of loops, but still no luck. I can get the error after a hundred or so connections, or maybe just after 1 or 2.

Here's the server loop:

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);
                }
            }

        }

I've tried checking if the write didn't write all requested byte, but it seemingly does. Interestingly enough, calling System.gc() after each newChannel.close() makes the problem disappear (but in return, it's horribly slow). So either I'm not releasing all resources I should release, or the application just needs a pause..

I'm losing all of my best years on this. Oh, and by the way.. if I ignore writing to the channel and just close after I accept the connection, the problem still doesn't go away.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

眉黛浅 2024-10-24 16:53:24

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

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

Well I found it out, so I might as well share it.

My app needed a pause. It was simply going too fast, and closing the connection before the client had written all of its request data. The fix would be to keep on reading until the entire HTTP request had been received. D'oh.. lesson learned.

忱杏 2024-10-24 16:53:24

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

尝试向通道写入最多 r 个字节,其中 r
缓冲区中剩余的字节数,即src.remaining()
目前该方法被调用。

[...]

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

您需要检查写入调用的返回值(您目前没有执行此操作),并发出连续的写入调用,直到发送整个缓冲区为止。我猜想是这样的:

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

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

From the docs for SocketChannel#Write (emphasis mine):

An attempt is made to write up to r bytes to the channel, where r is
the number of bytes remaining in the buffer, that is, src.remaining(),
at the moment this method is invoked.

[...]

Returns: The number of bytes written, possibly zero.

It's up to you to check the return value from the write call (which you're not doing presently), and issue successive write calls until the whole of the buffer has been sent. Something like this, I guess:

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

You'll obviously get aborts if you don't write all of your response data and then just close the socket.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文