java关闭通道_java – NIO Selector Thread,按预期处理通道,但如何确保通道在使用后正确关闭?...

所以我在ServerRunnable类中有以下代码:

public class FirmwareServerRunnable implements Runnable {

private static Logger log = Logger.getLogger(FirmwareServerRunnable.class

.getName());

private LinkedTransferQueue communicationQueue;

private int serverPort = 48485;

public FirmwareServerRunnable(int port,

LinkedTransferQueue communicationQueue) {

serverPort = port;

this.communicationQueue = communicationQueue;

}

private boolean running;

private ServerSocketChannel serverSocketChannel;

@Override

public void run() {

try {

Selector selector = Selector.open();

serverSocketChannel = ServerSocketChannel.open();

serverSocketChannel.configureBlocking(false);

ServerSocket serverSocket = serverSocketChannel.socket();

serverSocket.bind(new InetSocketAddress(serverPort));

log.info("Selector Thread: FirmwareServer Runnable- Listening for connections on port: "

+ serverSocket.getLocalPort());

running = true;

@SuppressWarnings("unused")

SelectionKey serverAcceptKey = serverSocketChannel.register(

selector, SelectionKey.OP_ACCEPT);

while (running) {

selector.select();

Set selectedKeys = selector.selectedKeys();

Iterator keyIterator = selectedKeys.iterator();

while (keyIterator.hasNext()) {

SelectionKey key = (SelectionKey) keyIterator.next();

if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) {

acceptConnection(selector, key);

keyIterator.remove();

} else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {

CommunicationState commsState = (CommunicationState) key

.attachment();

if (commsState.getCurrentState() == CommunicationState.STATE_READ) {

readFromSocketChannel(key);

keyIterator.remove();

}

} else if ((key.readyOps() & SelectionKey.OP_WRITE) == SelectionKey.OP_WRITE) {

CommunicationState commsState = (CommunicationState) key

.attachment();

if (commsState.getCurrentState() == CommunicationState.STATE_WRITE) {

writeToSocketChannel(key);

keyIterator.remove();

}

}

}

}

} catch (IOException e) {

log.error(

"Firmware Selector Thread: An IOException occurred",

e);

}

}

我的acceptConnection()方法接受一个连接,并向它添加一个CommunicationState对象(一个状态机),它包含ByteBuffer,当前通道状态,客户端当前在通信过程中等等…

此服务器在进程中间切换通信方法.最初它使用JSON消息与客户端进行通信,但是当它到达某一点时,它开始使用USART protocol commands使用新固件刷新客户端.

完成此过程后,客户端将断开连接并重新启动.这使我的频道处于未知状态.我不确定该频道是否已经关闭.

我怎么检查这个?我是否认为selector.selectedKeys()只返回准备好操作的键?如果是这种情况,我该如何检查未正确关闭的连接?在(运行){}循环中,我可以在此ServerRunnable中执行此操作吗?

我一直在考虑的一个选项是将一个对密钥本身的引用附加到CommunicationState机器上,然后我可以在进程完成后获得对该通道的引用并在那里关闭它.但由于某种原因,我对这个解决方案感到不安,对我来说感觉不对.

如果包含甚至关闭的频道密钥,我可以使用key.isValid()来确认密钥是否需要永久删除?

我很感激你对这个过程的任何想法,我必须忽视一些事情.

编辑:快速测试似乎表明,所选键组中不包含通道键,除非它们已准备好进行三个定义的操作之一

我的测试很糟糕.

最佳答案 已被对等方关闭的连接将导致选择器将您的频道视为可读,当您从中读取时,您将获得-1,因此您应关闭该频道,这将取消其选择键.

编辑

If it’s the case that even closed channel keys are included can I use key.isValid() to confirm that the key needs to be removed permanently?

如果您关闭了频道,其键将被取消,因此您下次在选定键集中将看不到它.如果对等方关闭了连接,请参见上文.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值