You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java NIO实现HTTP服务器返回响应后浏览器一直加载如何解决?

问题原因和修复方案

1. HTTP响应缺少结束标识,客户端无法判断数据传输完成

HTTP/1.1默认启用Keep-Alive持久连接,如果你没有明确告知客户端响应的总长度,客户端会一直等待后续数据,直到连接超时或者被主动断开。你终止Java程序时连接被强制关闭,浏览器才会认为响应结束,所以此时才会渲染内容。
解决方案二选一即可:

  • 在响应头增加Content-Length字段,准确填写响应体的字节长度,客户端收到对应长度的数据就会自动结束请求
  • 在响应头增加Connection: close字段,告知客户端响应发送完成后会直接关闭连接,客户端收到完整响应就会终止加载
    规范的响应示例(注意HTTP头的换行必须用\r\n,不能只用\n,否则会出现解析异常):
String response = "HTTP/1.1 200 OK\r\n"
                + "Content-Type: text/html; charset=UTF-8\r\n"
                + "Content-Length: 23\r\n"
                + "\r\n"
                + "<html><body>OK</body></html>";

上面示例中Content-Length的值为23,对应后面<html><body>OK</body></html>的UTF-8编码字节长度,需要根据实际响应内容准确计算。

2. 非阻塞SocketChannel写入逻辑存在缺陷

非阻塞模式下的SocketChannel.write()方法不保证一次性把缓冲区的所有数据写完,它只会写入内核发送缓冲区可容纳的字节数,返回实际写入的字节长度。你现在调用一次write就直接把感兴趣事件切回OP_READ,大概率会有部分数据残留在缓冲区没有发送,客户端收不到完整响应。
解决方案:写入后判断缓冲区是否还有剩余数据,如果还有就保留OP_WRITE事件,下次通道可写时继续发送,直到缓冲区所有数据写完再切换事件状态。
修改后的writeToKey参考代码:

private void writeToKey(SelectionKey key) throws IOException {
    SocketChannel clientSkt = (SocketChannel) key.channel();
    ClientState state = (ClientState) key.attachment();
    ByteBuffer buf = state.getWriteBuffer(); // 建议将待发送的缓冲区存在attach对象中,不要每次新建

    int written = clientSkt.write(buf);
    if (written < 0) {
        // 客户端已经主动断开连接,直接回收资源
        key.cancel();
        clientSkt.close();
        return;
    }
    if (buf.hasRemaining()) {
        // 还有数据未写完,继续监听可写事件
        key.interestOps(SelectionKey.OP_WRITE);
    } else {
        // 数据全部写完,如果使用短连接逻辑直接关闭即可,长连接则切回监听读事件
        key.interestOps(SelectionKey.OP_READ);
        // 短连接逻辑示例:
        // clientSkt.close();
        // key.cancel();
    }
}

其他注意事项

  • 你代码中的Srtring是拼写错误,正确写法为String,属于低级笔误,编译阶段就能发现
  • 读取请求的逻辑目前也存在问题:你只读一次缓冲区就认为请求读取完成,实际如果请求较大或者出现TCP分片,会出现一次读不完的情况,也需要和写入逻辑一样做累计读取处理,直到拿到完整的HTTP请求

内容的提问来源于stack exchange,提问作者Samuele B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 19:45:03