Mercurial > hg > RemoteEditor > REPSessionManager
view test/ServerSample.java @ 375:34642bc65c21
*** empty log message ***
author | kono |
---|---|
date | Wed, 22 Oct 2008 02:59:08 +0900 |
parents | 7107faaf3feb |
children | 4ec3b70f8f09 |
line wrap: on
line source
package test; import java.io.IOException; import java.nio.channels.*; import java.net.*; import rep.REPCommand; import rep.REPCommandPacker; import rep.channel.REPPack; import rep.channel.REPSelectionKey; import rep.channel.REPSelector; import rep.channel.REPServerSocketChannel; import rep.channel.REPSocketChannel; public class ServerSample { // client も書いて、standalone example として動くべき public static void main(String[] argv) throws Exception { // Thread base のSimulationか、実際のSocketかの選択 REPServerSocketChannel.isSimulation = false; // セレクタの用意 REPSelector<REPCommand> selector = REPSelector.create(); REPPack<REPCommand> pack = new REPCommandPacker(); // サーバソケットチャンネルを作成。5100番ポートを受付ポートに指定 // (非ブロックモードに設定:重要) REPServerSocketChannel<REPCommand> serverSocketChannel = REPServerSocketChannel.<REPCommand>open(pack); serverSocketChannel.configureBlocking(false); // この方法だと、IPv6 (Dual stack) 対応にならない.. // このホストの全てのアドレスを取得して、それ全部に対して、socketを開けて、すべてに対して、 // select する必要がある。 serverSocketChannel.socket().bind(new InetSocketAddress(5100)); // セレクタにサーバソケットチャンネルを登録。サーバへの受付を監視 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); // セレクタにイベントが通知されるごとに処理 while (true) { // セレクタにイベントが発生するまでブロック // select のreturn valueは信用しない。selectedKeys()を使う。 selector.select(); // 獲得したイベントごとに処理を実行 for (REPSelectionKey<REPCommand> selectionKey : selector.selectedKeys1()) { // java.nio だと for 文では動かないが、REPSocketChannel では動く // //for (Iterator<SelectionKey> it = keys.iterator();it.hasNext(); ) { // SelectionKey k = it.next(); // newKeys.add(new REPSelectionKey<P>(k,this)); // it.remove(); //} // と書く必要がある。 // サーバの受付処理: // イベントが受付可能である場合、受け付けるべき対象があれば // セレクタに取得したソケットチャンネルを登録 if (selectionKey.isAcceptable()) { // サーバソケットチャンネルからソケットチャンネルを獲得 // ソケットチャンネルを経由してクライアントと通信できる //SocketChannel socketChannel = serverSocketChannel.accept(); REPSocketChannel<REPCommand> socketChannel; socketChannel = selectionKey.accept(pack); // 接続先がなくてもここに処理が飛ぶことがある。対象が // nullの場合は処理を抜ける if (null == socketChannel) continue; // ソケットチャンネルを非ブロックモードに設定(重要)し、 // セレクタに読み込みを対象として登録 socketChannel.configureBlocking(false); socketChannel.register(selector, SelectionKey.OP_READ); socketChannel = null; } // クライアントとの通信処理 // 読込み可能である場合、内容物を読みこんで標準出力に表示。 // メッセージをクライアントに送信して、コネクションを切断。 // セレクタから登録を解除 else if (selectionKey.isReadable()) { // 登録されているソケットチャンネルを取得 REPSocketChannel<REPCommand> socketChannel = selectionKey.channel1(); REPCommand cmd = null; // クライアントからメッセージの受信 try { cmd = socketChannel.read(); } catch (IOException e) { // クライアント側が接続を切断していた場合は、サーバも // 接続を切断。セレクタから登録を削除 selectionKey.cancel(); // これは必要だと思う socketChannel.close(); // たぶん不要 } if (cmd==null) { // 読み込むべきメッセージは届いていないので処理を飛ばす // こういう場合もある continue; } // クライアントからメッセージを取得し、標準出力へ System.out.print("EEE: " + cmd); // クライアントへメッセージを送信 // copy or do not modify after the write // In the simulation, object is directly passed // to the client cmd = new REPCommand(cmd); cmd.setString("This is the answer."); socketChannel.write(cmd); // クライアントとの接続を切断。セレクタから登録を削除 socketChannel.close(); //break; } System.out.println(selectionKey.toString()); } } } }