はてなスーパーPre記法がScalaに対応したらしいのでEchoServerのソース貼ってみる
はてなスーパーPre記法がScalaに対応したらしいのでEchoServerのソース貼ってみます。
いちおう、Scala hack-a-thonの資料にも反映済み。
yuroyoro/scala-hackathon · GitHub
Dropbox - 404
普通のServerSocket版と、NIOノンブロッキングチャネル版の2種類書いてみましたが、ヒドいソースなんで添削希望ですだれかボスケテ。
ServerSocket版
import scala.actors.Actor import scala.actors.Actor._ import java.io._ import java.net.{ServerSocket, Socket } object EchoServer{ def main( args:Array[String] ) = { EchoActor.start() EchoActor ! Start( args.first.toInt ) } } case class Start( port:Int ) case class Wait( serverSocket:ServerSocket ) case class Accept( socket:Socket ) object EchoActor extends Actor { def act() = { loop{ react { case Start( port ) => { val serverSocket = new ServerSocket( port ) println( "EchoServeが起動しました。port=%d".format( port ) ) EchoActor ! Wait( serverSocket ) } case Wait( serverSocket ) => { val socket = serverSocket.accept val acceptActor = new AcceptActor acceptActor.start() acceptActor! Accept( socket ) EchoActor ! Wait( serverSocket ) } } } } } class AcceptActor extends Actor { def act() = { react { case Accept( socket ) => { val address = socket.getInetAddress println( address + ":[接続しました]" ) val in = new BufferedReader( new InputStreamReader(socket.getInputStream ) ) val out = new PrintWriter( socket.getOutputStream, true) val s = in.readLine println( "%s:%s".format( address , s ) ) out.println( s ) out.close in.close socket.close println( address + ":[切断しました]" ) } } } }
NIO ノンブロッキングチャネル版
import scala.actors.Actor import scala.actors.Actor._ import scala.collection.jcl.Conversions._ import java.net.InetSocketAddress import java.nio.ByteBuffer import java.nio.channels.{ SelectionKey, Selector, ServerSocketChannel, SocketChannel } import java.nio.charset.Charset object EchoServerNIO{ def main( args:Array[String] ){ EchoActor.start() EchoActor ! Start( args.first.toInt ) } } case class Select() case class Start( port:Int ) case class Accept( key:SelectionKey ) case class Read( key:SelectionKey ) object EchoActor extends Actor { val BUF_SIZE = 1024 lazy val selector = Selector.open lazy val serverChannel = ServerSocketChannel.open def act() = { loop { react { case Start( port ) => { serverChannel.configureBlocking(false) serverChannel.socket.bind( new InetSocketAddress( port ) ) serverChannel.register(selector, SelectionKey.OP_ACCEPT ) println( "EchoServeが起動しました。port=%d".format( port ) ) EchoActor ! Select } case Select => { selector.select selector.selectedKeys.foreach{ key => if( key.isAcceptable ){ EchoActor ! Accept( key ) } else if( key.isReadable ){ EchoActor ! Read( key ) } } EchoActor ! Select } case Accept( key ) => { val socket = key.channel.asInstanceOf[ServerSocketChannel] socket.accept match { case null => case channel => { val remoteAddress = channel.socket.getRemoteSocketAddress.toString(); println(remoteAddress + ":[接続しました]" ) channel.configureBlocking(false) channel.register(selector, SelectionKey.OP_READ); } } } case Read( key ) => { val channel = key.channel.asInstanceOf[SocketChannel] val buf = ByteBuffer.allocate(BUF_SIZE) val charset = Charset.forName("UTF-8") val remoteAddress = channel.socket.getRemoteSocketAddress.toString(); def close = { channel.close() println( remoteAddress + ":[切断しました]" ) } channel.read( buf ) match { case -1 => close case 0 => case x => { buf.flip println( "%s:%s".format( remoteAddress, charset.decode(buf).toString )) buf.flip channel.write( buf ) close } } } } } } }