最近P2Pにお熱/ソケットの勉強 - Scala

どうもポポです。
最近研究をやらずにP2Pの勉強ばかりしています。
というのもP2Pで動画キャッシュを共有できるアプリケーションを書いてみたいんですよね。
公開とかはまだまだ先になるかもしれないんですけど、がんばります。

さてその前にもっと基本的な部分を実験したみたい!ということで今日はソケットの実験を
やってみたいと思います。

ここでソケットの実験をやっているJavaのコードがあったのでこれをScalaで書こうかと思ったのですが、ちょっとコンパイルがうまくいかないとかなんとかあったので、こっちのscalaのサンプルコードを使ってみました。

・Server版

import java.io._
import java.net.{InetAddress,ServerSocket,Socket,SocketException}
import java.util.Random

object randomserver {

  def main(args: Array[String]): Unit = {
    try {
      println("クライアントからの接続をポート5555で待ちます")
      val listener = new ServerSocket(5555)
      while (true) new ServerThread(listener.accept()).start()
      listener.close()
    }
    catch {
      case e: IOException => System.err.println("Could not listen on port: 5555.")
        System.exit(-1)
    }
  }

}

case class ServerThread(socket: Socket) extends Thread("ServerThread") {

  override def run(): Unit = {
    val rand = new Random(System.currentTimeMillis())
    try {
      val out = new DataOutputStream(socket.getOutputStream())
      val in = new ObjectInputStream(new DataInputStream(socket.getInputStream()))
      val filter = in.readObject().asInstanceOf[Int => Boolean]

      while (true) {
        var succeeded = false;
        do {
          val x = rand.nextInt(1000);
          succeeded = filter(x);
          if (succeeded) out.writeInt(x)
        } while (! succeeded);
        Thread.sleep(100)
      }
      out.close()
      in.close()
      socket.close()
    }
    catch {
      case e: SocketException =>() // avoid stack trace when stopping a client with Ctrl-C
      case e: IOException => e.printStackTrace()
    }
  }
}

・Cilent版

import java.io._
import java.net.{InetAddress,ServerSocket,Socket,SocketException}
import java.util.Random

object randomclient {

  def main(args: Array[String]) {
    val filter: Int => Boolean = try {
      Integer.parseInt(args(0)) match {
        case 1 => x: Int => x % 2 != 0
        case 2 => x: Int => x % 2 == 0
        case _ => x: Int => x != 0
      }
    }
    catch {
      case _ => x: Int => x < 100
    }

    try {
      val ia = InetAddress.getByName("localhost")
      val socket = new Socket(ia, 5555)
      val out = new ObjectOutputStream(new DataOutputStream(socket.getOutputStream()))
      val in = new DataInputStream(socket.getInputStream())

      out.writeObject(filter)
      out.flush()

      while (true) {
        val x = in.readInt()
        println("x = " + x)
      }
      out.close()
      in.close()
      socket.close()
    }
    catch {
      case e: IOException => e.printStackTrace()
    }
  }

}

少し混ぜ混ぜしてますが、ちゃんと動くようですね。Socketの勉強になりましたでしょうかね?
流れとしては

・server版:サーバソケットで待ちポート指定→出力ストリーム取得→入力ストリーム取得→ごにょごにょ→順に閉じる
・client版:ソケット生成→出力ストリーム取得→入力ストリーム取得→ごにょごにょ→順に閉じる

ってな感じなのかなぁ。確かに感覚的にはわかった感じがするんだけど、理解していないような気がする。

ってかScalaむじぃ