在 Grpc-Android Java 中使用双向流时如何检测(物理)断开连接
How to detect (physical) disconnect when using a bidirectional stream in Grpc-Android Java
我使用 Bidirectional Streaming
的概念 Grpc
使用 Async stub
。
以下是我的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnOnline = (Button) findViewById(R.id.btnOnline);
btnOffline = (Button) findViewById(R.id.btnOffline);
btnAcceptRide = (Button) findViewById(R.id.btnAcceptRide);
btnCancelRide = (Button) findViewById(R.id.btnCancelRide);
txtCode = (EditText) findViewById(R.id.txtCode);
txtReply = (TextView) findViewById(R.id.txtReply);
ClientConnState = 0;
btnOnline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new GrpcTask().execute();
}
});
private class GrpcTask extends AsyncTask<Void, Void, String> {
private String mHost;
private String mMessage;
private int mPort;
private ManagedChannel mChannel;
@Override
protected void onPreExecute() {
mHost = "localhost";
mPort = 8080;
mChannel = ManagedChannelBuilder.forAddress("192.168.0.102", 50049)
.usePlaintext(true)
.build();
blockingStub = bidirectionalserviceGrpc.newBlockingStub(mChannel);
asyncStub = bidirectionalserviceGrpc.newStub(mChannel);
}
@Override
protected String doInBackground(Void... nothing) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
requestStreamObserver = asyncStub.requestRide(new StreamObserver<Bidirectional.RideReply>() {
@Override
public void onNext(Bidirectional.RideReply value) {
if (countDownLatch.getCount() > 0) {
countDownLatch.countDown();
}
}
@Override
public void onError(Throwable t) {
countDownLatch.countDown();
}
@Override
public void onCompleted() {
countDownLatch.countDown();
}
});
Bidirectional.RideRequest rideRequest = Bidirectional.RideRequest.newBuilder()
.setRequestid(1)
.setDrivercode(txtCode.getText().toString())
.build();
requestStreamObserver.onNext(rideRequest);
if (!countDownLatch.await(15, TimeUnit.SECONDS)) {
throw new RuntimeException(
"Could not finish rpc within 1 minute, the server is likely down");
}
return "completed";
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
return "Failed... : " + System.lineSeparator() + sw;
}
}
@Override
protected void onPostExecute(String result) {
Log.e(logger.getName(), result);
}
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Write Logic here
super.handleMessage(msg);
}
};
现在一切正常.. 我可以 ping/pong server/client 使用已建立的流。但是当我关闭服务器并从客户端发出流请求时,它会无限等待。我除了它抛出 OnError()
事件但它没有。
有人可以帮我解决这个问题吗?
根据服务器如何关闭以及客户端正在做什么,TCP 可能无法发现连接中断。您应该在 ManagedChannelBuilder
上启用 keepAliveTime()
。 Javadoc 应该可以帮助您入门,如果您有兴趣,A8-client-side-keepalive.md 有更多信息。
您可能还想启用 idleTimeout()
。
我使用 Bidirectional Streaming
的概念 Grpc
使用 Async stub
。
以下是我的代码
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnOnline = (Button) findViewById(R.id.btnOnline);
btnOffline = (Button) findViewById(R.id.btnOffline);
btnAcceptRide = (Button) findViewById(R.id.btnAcceptRide);
btnCancelRide = (Button) findViewById(R.id.btnCancelRide);
txtCode = (EditText) findViewById(R.id.txtCode);
txtReply = (TextView) findViewById(R.id.txtReply);
ClientConnState = 0;
btnOnline.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
new GrpcTask().execute();
}
});
private class GrpcTask extends AsyncTask<Void, Void, String> {
private String mHost;
private String mMessage;
private int mPort;
private ManagedChannel mChannel;
@Override
protected void onPreExecute() {
mHost = "localhost";
mPort = 8080;
mChannel = ManagedChannelBuilder.forAddress("192.168.0.102", 50049)
.usePlaintext(true)
.build();
blockingStub = bidirectionalserviceGrpc.newBlockingStub(mChannel);
asyncStub = bidirectionalserviceGrpc.newStub(mChannel);
}
@Override
protected String doInBackground(Void... nothing) {
try {
final CountDownLatch countDownLatch = new CountDownLatch(1);
requestStreamObserver = asyncStub.requestRide(new StreamObserver<Bidirectional.RideReply>() {
@Override
public void onNext(Bidirectional.RideReply value) {
if (countDownLatch.getCount() > 0) {
countDownLatch.countDown();
}
}
@Override
public void onError(Throwable t) {
countDownLatch.countDown();
}
@Override
public void onCompleted() {
countDownLatch.countDown();
}
});
Bidirectional.RideRequest rideRequest = Bidirectional.RideRequest.newBuilder()
.setRequestid(1)
.setDrivercode(txtCode.getText().toString())
.build();
requestStreamObserver.onNext(rideRequest);
if (!countDownLatch.await(15, TimeUnit.SECONDS)) {
throw new RuntimeException(
"Could not finish rpc within 1 minute, the server is likely down");
}
return "completed";
} catch (Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
pw.flush();
return "Failed... : " + System.lineSeparator() + sw;
}
}
@Override
protected void onPostExecute(String result) {
Log.e(logger.getName(), result);
}
}
final Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
// Write Logic here
super.handleMessage(msg);
}
};
现在一切正常.. 我可以 ping/pong server/client 使用已建立的流。但是当我关闭服务器并从客户端发出流请求时,它会无限等待。我除了它抛出 OnError()
事件但它没有。
有人可以帮我解决这个问题吗?
根据服务器如何关闭以及客户端正在做什么,TCP 可能无法发现连接中断。您应该在 ManagedChannelBuilder
上启用 keepAliveTime()
。 Javadoc 应该可以帮助您入门,如果您有兴趣,A8-client-side-keepalive.md 有更多信息。
您可能还想启用 idleTimeout()
。