Java/Kotlin实现HTTP/2双向流式通信对接PHP长连接服务
需求与问题场景
我有一个PHP脚本,可接收HTTP/2长连接,并在客户端流式传输数据片段时对其进行处理,客户端向服务器流式传输的数据总量预计可达5GB。每接收一段数据后,服务器会返回包含相关信息的JSON响应。
核心约束:
- 该PHP脚本不能作为独立应用(不支持WebSocket的独立PHP服务器不可行,因此选择HTTP/2)
- 必须在单个连接上完成,不能拆分为多个请求
- 传输的数据为二进制类型
遇到的问题
我尝试使用Ktor、OkHttp和Java 11 HTTP Client,但都遇到同一个问题:必须等请求完成后才能使用响应体。而核心需求是实现双向交错通信——HTTP/2的RFC明确支持该特性。
我的思路是:由某个线程向OutputStream写入数据,通过管道将数据传入HTTP客户端;同一线程使用连接的InputStream接收响应。但实际情况是,响应处理部分永远不会执行,因为HTTP客户端会等待OutputStream关闭。
尝试的代码
OkHttp 实现代码(Kotlin)
val request = Request.Builder() .url("/media".customApiUrl) .post(object : RequestBody() { override fun contentType(): MediaType = "application/octet-stream".toMediaType() override fun writeTo(sink: BufferedSink) { sink.writeAll(pipeIn.source()) } }) .build() OkHttpClient().newBuilder() .protocols(listOf(Protocol.H2_PRIOR_KNOWLEDGE)) .build() .newCall(request).enqueue(object : Callback { override fun onFailure(call: Call, e: IOException) { TODO("Not yet implemented") } override fun onResponse(call: Call, response: Response) { // this is never called logger.debug("Media session executing") } })
Ktor 实现代码(Kotlin)
logger.debug("Making HTTP call") httpClient.preparePut("/media".customApiUrl) { contentType(ContentType("application", "octet-stream")) setBody(pipeIn) logger.debug("Media session ready to execute") }.execute { // This is never called (checked using breakpoint) logger.debug("Media session executing") } // this is also never called but that's fine logger.info("Media session closed")
流创建代码
val pipeOut = PipedOutputStream() val pipeIn = PipedInputStream().also { it.connect(pipeOut) }
注:pipeOut的使用方式和存储位置已省略(与问题无关)。即使尚未传输任何字节,也应触发调试日志语句,以便使用响应的InputStream。
求助需求
我需要任何运行在JVM上且支持HTTP/2的Java或Kotlin解决方案,要求连接的InputStream和OutputStream可随时读写,无需等待所有数据传输至服务器。
补充说明:目前我也在调试PHP脚本,欢迎针对上述场景提供解决方案或代码修正建议。
内容的提问来源于stack exchange,提问作者Simao Gomes Viana
相关产品推荐
相关产品推荐

