私はたくさんのドキュメント、フォーラム、そしてもちろんあなたのそれぞれの回答を読みました。ソリューションを開発してテストしました。これは最善ではありませんが、私の最良の概算です。
SelectorのselectNow()メソッドを使用します。SocketChannelが登録されている名前を指定すると、このメソッドを使用して、関連付けられたSocketに読み取り可能なバイトがあるかどうかを知ることができます。Selector
selector
public boolean isReadable() {
try {
selector.selectNow();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while(keyIterator.hasNext()) {
SelectionKey selectionKey = keyIterator.next();
if(!selectionKey.isValid()) {
continue;
}
if(selectionKey.isReadable()) {
return true;
}
keyIterator.remove();
}
} catch(IOException e) {
// error
}
return false;
}
バイトを読み取らずにソケットに読み取り可能なバイトがあるかどうかを知る唯一の方法です。それを行うためのより良い方法またはこの方法で行うことの欠点を知っていますか?
編集:
このソリューションは初めて機能しますが、欠点があります。0 バイトが読み取れる場合でも、常に true を返します。データが利用できない場合でも、ソケットを読み取ることができます。読み取りバッファーにデータがない場合は読み取りたくないので、これは私が望む動作ではありません。
EDIT2 BIS:
このコードをテストします。
public static boolean isReadable(Selector selector) {
try {
selector.selectNow();
Set<SelectionKey> selectedKeys = selector.selectedKeys();
Iterator<SelectionKey> keyIterator = selectedKeys.iterator();
while (keyIterator.hasNext()) {
SelectionKey selectionKey = keyIterator.next();
if (!selectionKey.isValid()) {
continue;
}
if (selectionKey.isReadable()) {
keyIterator.remove();
return true;
}
keyIterator.remove();
}
} catch (IOException e) {
System.err.println("Error!");
e.printStackTrace();
}
return false;
}
public static void read() {
try {
Selector selector = Selector.open();
SocketChannel socketChannel = SocketChannel.open();
Socket socket = socketChannel.socket();
System.out.println("Connecting to server...");
socket.connect(new InetSocketAddress("localhost", 9999));
System.out.println("Connected to server.");
socketChannel.configureBlocking(false);
socketChannel.register(selector, SelectionKey.OP_READ);
ByteBuffer bb = ByteBuffer.allocate(1024);
while (true) {
boolean readable = isReadable(selector);
if (readable) {
System.out.println("Readable data found! Let's read...");
bb.clear();
int readBytes = socketChannel.read(bb);
if (readBytes < 0) {
System.out.println("End of Stream found");
break;
}
byte[] readArray = new byte[readBytes];
System.arraycopy(bb.array(), 0, readArray, 0, readBytes);
System.out.println("Read (" + (readBytes) + " bytes): "
+ new String(readArray, Charset.forName("UTF-8")));
bb.flip();
socketChannel.write(bb);
Thread.sleep(1000);
} else {
System.out.println("No data to read, sleeping");
Thread.sleep(1000);
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
read();
}
まず、接続をリッスンしてデータを書き込むアプリケーションを実行します。次のコマンドでnetcatnc -l 9999
を使用しました。次に、Java プログラムを実行します。最後に、テキスト行を書き込むことができnetcat
、私の Java プログラムは完全に動作します。
これは概念実証であり、実際のプログラミング ソリューションへの道ではないことに注意してください。実際、これは非常に悪い習慣です。@EJPと@Markusに感謝します!