我正在尝试使用MINA 2.0 RC1在基于demux的客户端应用程序中执行同步写入/读取,但它似乎陷入困境。这是我的代码:
public boolean login(final String username, final String password) {
// block inbound messages
session.getConfig().setUseReadOperation(true);
// send the login request
final LoginRequest loginRequest = new LoginRequest(username, password);
final WriteFuture writeFuture = session.write(loginRequest);
writeFuture.awaitUninterruptibly();
if (writeFuture.getException() != null) {
session.getConfig().setUseReadOperation(false);
return false;
}
// retrieve the login response
final ReadFuture readFuture = session.read();
readFuture.awaitUninterruptibly();
if (readFuture.getException() != null) {
session.getConfig().setUseReadOperation(false);
return false;
}
// stop blocking inbound messages
session.getConfig().setUseReadOperation(false);
// determine if the login info provided was valid
final LoginResponse loginResponse = (LoginResponse)readFuture.getMessage();
return loginResponse.getSuccess();
}
我可以在服务器端看到检索到LoginRequest对象,并发送LoginResponse消息。在客户端,DemuxingProtocolCodecFactory
收到响应,但在投入一些日志记录后,我可以看到客户端卡在readFuture.awaitUninterruptibly()
的调用上。
我不能为我的生活弄清楚为什么它会根据我自己的代码卡在这里。我在会话配置中正确地将读取操作设置为true,这意味着应该阻止消息。但是,当我尝试同步读取响应消息时,似乎消息不再存在。
为什么这对我不起作用的任何线索?
答案 0 :(得分:0)
这对我不起作用的原因是因为我的代码中的其他地方出现了一个问题,我愚蠢地忽略了实现消息响应编码器/解码器。啊。无论如何,我的问题中的代码一旦解决了就会起作用。
答案 1 :(得分:0)
我遇到了这个问题。事实证明,这是因为我在IoHandler.sessionCreated()实现中进行读/写操作。我将处理移动到建立连接的线程上,而不是等待近期。
答案 2 :(得分:0)
我喜欢这个(克里斯蒂安·穆勒:http://apache-mina.10907.n7.nabble.com/Mina-Client-which-sends-receives-messages-synchronous-td35672.html)
public class UCPClient {
private Map<Integer, BlockingQueue<UCPMessageResponse>> concurrentMap = new ConcurrentHashMap<Integer, BlockingQueue<UCPMessageResponse>>();
// some other code
public UCPMessageResponse send(UCPMessageRequest request) throws Throwable {
BlockingQueue<UCPMessageResponse> queue = new LinkedBlockingQueue<UCPMessageResponse>(1);
UCPMessageResponse res = null;
try {
if (sendSync) {
concurrentMap.put(Integer.valueOf(request.getTransactionReference()), queue);
}
WriteFuture writeFuture = session.write(request);
if (sendSync) {
boolean isSent = writeFuture.await(transactionTimeout, TimeUnit.MILLISECONDS);
if (!isSent) {
throw new TimeoutException("Could not sent the request in " + transactionTimeout + " milliseconds.");
}
if (writeFuture.getException() != null) {
throw writeFuture.getException();
}
res = queue.poll(transactionTimeout, TimeUnit.MILLISECONDS);
if (res == null) {
throw new TimeoutException("Could not receive the response in " + transactionTimeout + " milliseconds.");
}
}
} finally {
if (sendSync) {
concurrentMap.remove(Integer.valueOf(request.getTransactionReference()));
}
}
return res;
}
}
和IoHandler:
public class InnerHandler implements IoHandler {
// some other code
public void messageReceived(IoSession session, Object message) throws Exception {
if (sendSync) {
UCPMessageResponse res = (UCPMessageResponse) message;
BlockingQueue<UCPMessageResponse> queue = concurrentMap.get(res.getTransactionReference());
queue.offer(res);
}
}
}
答案 3 :(得分:-1)
您不得在login()
帖子中使用IoHandler
功能:
如果您在IoFuture.awaitUninterruptibly()
的覆盖事件功能中调用IoHandler
,
IoHandler无法工作并陷入困境。
您可以在其他主题中调用login()
,它将正常工作。