JavaNIO-ServerSocketチャネル

Java NIOサーバーソケットチャネルは、ソケットを接続するストリーム指向のデータフローに使用される選択可能なタイプのチャネルです。サーバーソケットチャネルは、静的なものを呼び出すことで作成できます。 open() メソッド、既存のソケットを提供することはまだ存在していません。サーバーソケットチャネルは、openメソッドを呼び出すことによって作成されますが、まだバインドされていません。ソケットチャネルをバインドするために bind() メソッドが呼び出されます。

ここで言及する1つのポイントは、チャネルがバインドされておらず、I / O操作が試行された場合、このチャネルによってNotYetBoundExceptionがスローされるため、IO操作を実行する前にチャネルがバインドされていることを確認する必要があります。

サーバーソケットチャネルの着信接続は、ServerSocketChannel.accept()メソッドを呼び出すことによってリッスンされます。accept()メソッドが戻ると、着信接続のあるSocketChannelを返します。したがって、accept()メソッドは着信接続が到着するまでブロックします。チャネルが非ブロッキングモードの場合、保留中の接続がない場合、acceptメソッドはすぐにnullを返します。それ以外の場合は、新しい接続が使用可能になるか、I / Oエラーが発生するまで、無期限にブロックされます。

新しいチャネルのソケットは最初はバインドされていません。接続を受け入れる前に、ソケットのバインドメソッドの1つを介して特定のアドレスにバインドする必要があります。また、新しいチャネルは、システム全体のデフォルトのSelectorProviderオブジェクトのopenServerSocketChannelメソッドを呼び出すことによって作成されます。

ソケットチャネルのようにサーバーソケットチャネルはを使用してデータを読み取ることができます read()最初に、バッファが割り当てられます。ServerSocketChannelから読み取られたデータは、バッファーに格納されます。次に、ServerSocketChannel.read()メソッドを呼び出して、ServerSocketChannelからバッファーにデータを読み取ります。read()メソッドの整数値は、バッファに書き込まれたバイト数を返します

同様に、データはを使用してサーバーソケットチャネルに書き込むことができます write() パラメータとしてバッファを使用するメソッド。通常、バッファに書き込み可能なバイトがなくなるまでwrite()メソッドを繰り返す必要があるため、whileループでwriteメソッドを使用します。

ソケットチャネルの重要な方法

  • bind(SocketAddress local) −このメソッドは、このメソッドのパラメータとして提供されるローカルアドレスにソケットチャネルをバインドするために使用されます。

  • accept() −このメソッドは、このチャネルのソケットへの接続を受け入れるために使用されます。

  • connect(SocketAddress remote) −この方法は、ソケットをリモートアドレスに接続するために使用されます。

  • finishConnect() −この方法は、ソケットチャネルを接続するプロセスを終了するために使用されます。

  • getRemoteAddress() −このメソッドは、チャネルのソケットが接続されているリモートロケーションのアドレスを返します。

  • isConnected() −すでに述べたように、このメソッドはソケットチャネルの接続ステータス、つまり接続されているかどうかを返します。

  • open() − openメソッドは、指定されていないアドレスのソケットチャネルを開くために使用されます。この便利なメソッドは、open()メソッドを呼び出し、結果のサーバーソケットチャネルでconnectメソッドを呼び出し、リモートで渡し、そのチャネルを返すかのように機能します。

  • read(ByteBuffer dst) −このメソッドは、ソケットチャネルを介して指定されたバッファからデータを読み取るために使用されます。

  • setOption(SocketOption<T> name, T value) −このメソッドは、ソケットオプションの値を設定します。

  • socket() −このメソッドは、このチャネルに関連付けられているサーバーソケットを取得します。

  • validOps() −このメソッドは、このチャネルでサポートされている操作を識別する操作セットを返します。サーバーソケットチャネルは、新しい接続の受け入れのみをサポートするため、このメソッドはSelectionKey.OP_ACCEPTを返します。

次の例は、Java NIOServerSocketChannelからデータを送信する方法を示しています。

C:/Test/temp.txt

Hello World!

クライアント:SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

出力

クライアントを実行すると、サーバーが起動するまで何も出力されません。

サーバー:SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

出力

サーバーを実行すると、次のように出力されます。

Connection Set:  /127.0.0.1:49558
File Received