这是重要的代码:
public void setSelector() {
try {
this.writebuf.clear();
this.selector = Selector.open();
int interestSet = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
SelectionKey selectionKey = this.socketChannel.register(selector, interestSet);
// Checking if the buffer is in write mode
if (!(this.writebuf.limit() == this.writebuf.capacity())) {
writebuf.flip();
}
int bytesRead = 0;
while (selector.select() > -1) {
// Wait for an event one of the registered channels
// Iterate over the set of keys for which events are available
Iterator selectedKeys = selector.selectedKeys().iterator();
while (selectedKeys.hasNext()) {
SelectionKey key = (SelectionKey) selectedKeys.next();
selectedKeys.remove();
if (!key.isValid()) {
continue;
}
if (key.isReadable()) {
bytesRead = this.socketChannel.read(this.writebuf);
if (bytesRead > 0 && writebuf.hasRemaining()) {
this.writebuf.flip();
this.parseSubtitleMessage(new String(writebuf.array(), charset));
this.writebuf.clear();
this.writebuf.flip();
}
}
if (key.isWritable()) {
// Not yet implemented
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
Socketchannel
设置为nonblocking
模式。
第一个问题是while循环会产生巨大的工作量。基本上我需要在pause
或READ
WRITE
出现之前event
代码的内容。
另一个有问题的部分是此代码:
this.parseSubtitleMessage(new String(writebuf.array(), charset));
我知道当我调用array()
方法时,即使我调用forgotten
方法,我也会从前一条消息中获取整个缓冲区,包括一些clear
个字节。我找到了一个使用while循环迭代单个字节的解决方案,直到buffer.hasRemaining()
设置为false。但在这种情况下我不知道如何使用指定的字符集。
编辑: 我解决了我的“无限循环”问题,这里是固定代码:
public void runSelector() {
try {
this.writebuf.clear();
// Checking if the buffer is in write mode
if (!(this.writebuf.limit() == this.writebuf.capacity())) {
writebuf.flip();
}
this.selector = Selector.open();
int interestSet_RW = SelectionKey.OP_READ | SelectionKey.OP_WRITE;
int bytesRead = 0;
SelectionKey selectionKey = this.socketChannel.register(selector, SelectionKey.OP_READ);
while(true) {
int readyChannels = selector.select();
if(readyChannels == 0) continue;
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {
SelectionKey key = keyIterator.next();
if (!key.isValid()) {
continue;
}
// Check if there's something to write in the queue and change interestops apropriately.
if (monitorObject.tosendIsEmpty()) {
selectionKey.interestOps(SelectionKey.OP_READ);
} else {
selectionKey.interestOps(interestSet_RW);
}
if (key.isWritable()) {
}
if (key.isReadable()) {
bytesRead = this.socketChannel.read(this.writebuf);
if (bytesRead > 0 && writebuf.hasRemaining()) {
this.parseSubtitleMessage(new String(this.writebuf.array(), charset));
this.writebuf.clear();
}
}
keyIterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
我无意中创建了一个重复的线程。那天我的谷歌技能可能非常糟糕。 然而,第二个问题仍然存在,我将非常感谢你的帮助。感谢
编辑2:所以我也解决了第二个问题。这是代码:
if (key.isReadable()) {
bytesRead = this.socketChannel.read(this.writebuf);
bytes = new byte[bytesRead];
int x = 0;
this.writebuf.flip();
while(this.writebuf.hasRemaining()) {
bytes[x] = this.writebuf.get();
x++;
}
System.out.println(new String(bytes, charset));
this.writebuf.flip();
this.writebuf.clear();
}