【Java】SocketChannel / ServerSocketChannel ~ブロッキングモード編~

ブロッキングモード / ノンブロッキングモード

ブロッキングモード

 * 読み込みや書き込みを完了するまで待つ(=制御をブロックする)

API

 * java.net.ServerSocket

ノンブロッキングモード

 * 今できる処理(read/write)して、すぐに制御が戻る
 * ノンブロッキングモードの詳細は以下の関連記事を参照のこと
http://blogs.yahoo.co.jp/dk521123/35120798.html

API

 * java.nio.channels.ServerSocketChannel(ブロッキングモード / ノンブロッキングモードどちらも使える)
 * java.nio.channels.AsynchronousServerSocketChannel

サンプル

サーバ側

ChannelSampleServer.java

* 実行しておく
import java.net.InetSocketAddress;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;

public class ChannelSampleServer {
   public static final int PORT = 12345;

   public static void main(String[] args) {
      ChannelSampleServer server = new ChannelSampleServer();
      server.start();
   }

   public void start() {
      try (ServerSocketChannel serverChannel = ServerSocketChannel.open();) {
         serverChannel.socket().bind(new InetSocketAddress(PORT));
         System.out.println("起動しました port = "
               + serverChannel.socket().getLocalPort());
         while (true) {
            SocketChannel channel = serverChannel.accept();
            System.out.println(channel.socket().getRemoteSocketAddress()
                  + " : 接続されました");
            ChannelServerThread channelServerThread = new ChannelServerThread(channel);
            channelServerThread.start();
         }
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
}

ChannelServerThread.java

import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class ChannelServerThread extends Thread {
   private static final int BUFFER_SIZE = 1000;
   private SocketChannel channel = null;

   public ChannelServerThread(SocketChannel channel) {
      this.channel = channel;
   }

   public void run() {
      ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
      String remoteAddress = this.channel.socket().getRemoteSocketAddress()
            .toString();
      try {
         if (this.channel.read(buffer) < 0) {
            return;
         }
         buffer.flip();
         Charset charset = Charset.forName("UTF-8");
         String input = charset.decode(buffer).toString();
         System.out.print(remoteAddress + " : " + input);
         buffer.flip();
         this.channel.write(buffer);
      } catch (Exception ex) {
         ex.printStackTrace();
         return;
      } finally {
         System.out.println(remoteAddress + " : 切断しました ");
         if (this.channel != null && this.channel.isOpen()) {
            try {
               this.channel.close();
            } catch (IOException e) {
            }
         }
      }
   }
}

クライアント側

ChannelSampleClient.java

* サーバ側を起動したら、こちらを起動する
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.channels.SocketChannel;
import java.nio.charset.Charset;

public class ChannelSampleClient {
   public static final int PORT = 12345;
   public static final int BUFFER_SIZE = 1000;

   public static void main(String[] args) {
      try (SocketChannel channel = SocketChannel.open(new InetSocketAddress("localhost",
            PORT));) {
         BufferedReader in = new BufferedReader(new InputStreamReader(
               System.in));
         System.out.print("送信:");
         String line = in.readLine();
         ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE);
         Charset charset = Charset.forName("UTF-8");
         channel.write(charset.encode(CharBuffer.wrap(line + "\n")));
         while (channel.isConnected()) {
            buffer.clear();
            if (channel.read(buffer) < 0) {
               return;
            }
            buffer.flip();
            System.out.print("受信:" + charset.decode(buffer).toString());
         }
      } catch (Exception ex) {
         ex.printStackTrace();
      }
   }
}

出力結果

■ クライアント側の表示

「hellow」って入力すると...
送信:hellow
受信:hellow

■ サーバ側の表示

起動しました port = 12345
/127.0.0.1:63073 : 接続されました
/127.0.0.1:63073 : hellow
/127.0.0.1:63073 : 切断しました 


関連記事

SocketChannel / ServerSocketChannel ~ノンブロッキングモード編~

http://blogs.yahoo.co.jp/dk521123/35120798.html

Socket 通信を行う ~Server側/Client側の実装例~

http://blogs.yahoo.co.jp/dk521123/33075148.html

Java で、SSL通信を行うには

http://blogs.yahoo.co.jp/dk521123/33122920.html