Мы создаем приложение, в котором оно записывает голос пользователя в режиме реального времени и отправляет записанные данные на сервер через HTTP-запрос. В то время как сервер обрабатывает данные в реальном времени, он также отправляет ответы в виде чанков. Проще говоря, приложение отправляет данные по частям на сервер, и в то же время оно также получает по частям ответы от сервера.
Пожалуйста, НЕ говорите мне, что это невозможно потому что у меня есть рабочий пример в iOS, который использует URLSession
с uploadTask
, используя пару потоков для отправки данных в режиме реального времени на сервер, а затем получает ответы по частям от этого обратного вызова urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
.
Ниже мой код в Java. Я получил отправку, но ответ получен только после завершения отправки.
RequestBody body = new RequestBody()
{
@Override
public MediaType contentType()
{
return MediaType.get("application/octet-stream");
}
@Override
public void writeTo(BufferedSink sink) throws IOException
{
String filename = "/path/spoken.pcm";
try
{
InputStream inputStream = new DataInputStream(new FileInputStream(new File(filename)));
byte[] cacheBytes = new byte[320];
int length;
while((length = inputStream.read(cacheBytes, 0, cacheBytes.length)) != -1)
{
System.out.println("write thread name: " + Thread.currentThread());
sink.write(cacheBytes, 0, length);
Thread.sleep(10);
}
inputStream.close();
}
catch(IOException | InterruptedException e)
{
e.printStackTrace();
}
}
};
Request request = new Request.Builder()
.url("www.server.com")
.post(body)
.build();
Interceptor interceptor = new Interceptor()
{
@Override
public Response intercept(Chain chain) throws IOException
{
System.out.println("intercept!!!");
CountDownLatch latch = new CountDownLatch(1);
Response response = chain.proceed(chain.request());
BufferedSource source = response.body().source();
System.out.println("got response body !!!!");
new Thread(new Runnable()
{
@Override
public void run()
{
byte[] cachedBytes = new byte[512];
try
{
while(!source.exhausted())
{
int length = source.read(cachedBytes);
byte[] partialBytes = new byte[length];
System.arraycopy(cachedBytes, 0, partialBytes, 0, length);
System.out.println("partial response received: " + getHexString(partialBytes));
}
}
catch (IOException e)
{
e.printStackTrace();
}
latch.countDown();
}
}).start();
try
{
latch.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
}
return response;
}
};
httpClient = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.build();
httpClient.newCall(request).enqueue(new Callback()
{
@Override
public void onFailure(Call call, IOException e)
{
e.printStackTrace();
}
@Override
public void onResponse(Call call, Response response) throws IOException
{
try(ResponseBody responseBody = response.body())
{
if(!response.isSuccessful()) throw new IOException("Unexpected code " + response);
System.out.println("all responses received!");
}
}
});
Этот журнал: System.out.println("got response body !!!!");
отображается только после завершения отправки всех данных на сервер. Это означает, что когда writeTo(BufferedSink sink)
возвращается, я получаю ответ в обратном вызове перехватчика порциями, а затем вызывается обратный вызов onResponse(Call call, Response response)
.
Что мне нужно, так это то, что когда я отправляю данные, я хочу иметь возможность получать чанкованные ответы одновременно.