私はJava NIOで新しく、チュートリアルを読んだ後、簡単なNIOサーバーとクライアントを作成しようとしました。 私のサーバはクライアントからのリッスンとコンソールへの印刷という単純なことを行い、クライアントは単にサーバに接続し、3つのメッセージ "Hello"を送信します。 問題は私のサーバーが3つのメッセージを聞いてうまく動作することです。その後、ブロックしてリスニングを続ける必要がありますが、ブロッキングはなく、ループ中は無限に実行されます。ここに私のサーバーとクライアントです:セレクタ付き無限ループもクライアントからの接続がありません
サーバー
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.util.Iterator;
import java.util.Set;
public class Server {
public static void main(String args[]) throws Exception {
// Create the server socket channel
ServerSocketChannel server = ServerSocketChannel.open();
// nonblocking I/O
server.configureBlocking(false);
// host-port 8000
server.socket().bind(new InetSocketAddress(8000));
System.out.println("Server actives at port 8000");
// Create the selector
Selector selector = Selector.open();
// Recording server to selector (type OP_ACCEPT)
server.register(selector, SelectionKey.OP_ACCEPT);
while (selector.select() > 0) {
// Get keys
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
// print
System.out.println("[ " + keys.size() + " ]");
// For each keys...
while (i.hasNext()) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// if isAccetable = true
// then a client required a connection
if (key.isAcceptable()) {
// get client socket channel
SocketChannel client = server.accept();
// Non Blocking I/O
client.configureBlocking(false);
// recording to the selector (reading)
client.register(selector, SelectionKey.OP_READ);
continue;
}
// if isReadable = true
// then the server is ready to read
if (key.isReadable()) {
SocketChannel client = (SocketChannel) key.channel();
// Read byte coming from the client
int BUFFER_SIZE = 1024;
ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
try {
client.read(buffer);
} catch (Exception e) {
// client is no longer active
e.printStackTrace();
}
// Show bytes on the console
buffer.flip();
Charset charset = Charset.forName("ISO-8859-1");
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(buffer);
System.out.println("[" + charBuffer.toString() + "]");
}
}
}
}
}
そして、ここでは私のクライアントです:
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;
public class Client {
public static void main(String args[]) throws Exception {
// Create client SocketChannel
SocketChannel client = SocketChannel.open();
// nonblocking I/O
client.configureBlocking(false);
// Connection to host port 8000
client.connect(new java.net.InetSocketAddress("127.0.0.1", 8000));
// Create selector
Selector selector = Selector.open();
// Record to selector (OP_CONNECT type)
SelectionKey clientKey = client.register(selector,
SelectionKey.OP_CONNECT);
int counter = 0;
boolean chk = true;
// Waiting for the connection
while (selector.select(500) > 0 && chk) {
// Get keys
Set<SelectionKey> keys = selector.selectedKeys();
Iterator<SelectionKey> i = keys.iterator();
// For each key...
while (i.hasNext() && chk) {
SelectionKey key = (SelectionKey) i.next();
// Remove the current key
i.remove();
// Get the socket channel held by the key
SocketChannel channel = (SocketChannel) key.channel();
// Attempt a connection
if (key.isConnectable()) {
// Connection OK
System.out.println("Server Found");
// Close pendent connections
if (channel.isConnectionPending())
channel.finishConnect();
// Write continuously on the buffer
ByteBuffer buffer = null;
for (;chk;counter++) {
Thread.sleep(1000);
buffer = ByteBuffer.wrap(new String(" Client ").getBytes());
channel.write(buffer);
buffer.clear();
if (counter == 2)
{
chk = false;
client.close();
}
}
}
}
}
}
}
誰もが私のコードが間違っているかを説明できますか? ありがとうございます。
あなたの答えはありがたいですが、さらに質問があります。なぜ3つのメッセージを受信する前にブロックされているのですか?その後、ブロックされません。 – Leo
私はあなたの答えを見直しました。 "何も準備ができていなければ、それはちょうどループし続けるでしょう"と思うのですが、その時点で正しいと思いますが、ループは 'selector.select()'によってブロックされます。ない? – Leo
読み取りが失敗しない限り、非ブロッキングでピアが切断されたことを検出することはできません。したがって、selectは読み込み準備が整ったと考えて、読み込み可能な選択キーを常に返します。それが有効であるかどうかを検出し、読み込みが失敗した場合にキーをキャンセルするのはあなたの責任です。以下のようにサーバー側を変更してください。 SocketChannelクライアント=(SocketChannel)key.channel(); int BUFFER_SIZE = 1024; ByteBufferバッファ= ByteBuffer.allocate(BUFFER_SIZE); int bytesread = client.read(バッファ); if(bytesread == -1){key.cancel(); client.close();持続する; } – Drona