here is the important code:
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
is set to nonblocking
mode.
The first problem is that the while loop creates huge workload. Basically I need something that would pause
the code until the READ
or WRITE
event
occurs.
Another problematic part is this code:
this.parseSubtitleMessage(new String(writebuf.array(), charset));
I know that when I call the array()
method I'll get the whole buffer including some forgotten
bytes from the previous message, even though I call the clear
method. I found a solution that uses a while cycle to iterate over single bytes until the buffer.hasRemaining()
is set to false. But I don't know how to use the specified charset in this case.
Edit: I solved my "infinite loop" problem, here is the fixed code:
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();
}
}
I unintentionally created sligthly duplicate thread. My google skills were probably really bad that day. However the second problem still remains and I'll definitely appreciate your help. Thanks
Edit 2: So I fixed my second problem too. Here is the code:
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();
}
Here is the final solution:
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;
byte[] bytes = null;
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);
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();
}
keyIterator.remove();
}
}
} catch (IOException e) {
e.printStackTrace();
}
}