Что случилось с моими EchoServer и EchoClient на основе сокетов? - PullRequest
2 голосов
/ 04 ноября 2011

Я написал EchoServer на основе сокетов и EchoClient:

package socket.echo

import actors.Actor
import java.net.{InetSocketAddress, Socket, ServerSocket}
import java.io.{ByteArrayOutputStream, InputStream, OutputStream}

object EchoServer {
  def main(args: Array[String]): Unit = {
    val port = if (args.length > 1 && args(0) != null) args(0).toInt else 8080;
    val backlog = if (args.length > 2 && args(1) != null) args(1).toInt else 50;
    new EchoServer(port, backlog).start()
  }
}

class EchoServer(val port: Int, val backlog: Int) extends Actor {
  def act() {
    val serverSocket = new ServerSocket(port, backlog)
    println("Create a serverSocket: " + serverSocket)
    var isStop = false
    while (!isStop) {
      val socket = serverSocket.accept();
      println("Create a socket " + socket)
      Actor.actor {
        val is = socket.getInputStream
        val os = socket.getOutputStream
        val buf = IO.read(is)
        os.write(buf)
        os.flush()
        is.close()
        os.close()
        val msg = new String(buf, "UTF-8")
        println("Receive " + msg + " from " + socket)
        if ("quit".equalsIgnoreCase(msg)) isStop = true
        socket.close()
      }
    }
    println("Server stop! ")
  }
}

object IO {
  val BYTE_BLOCK_LENGTH = 1024
  /**
   * The input and output stream won't be closed after the method invocation
   *
   * @param is
   * @param os
   */
  def copy(is: InputStream, os: OutputStream): Unit = {
    var buf = new Array[Byte](BYTE_BLOCK_LENGTH)
    var isStop = false
    while (!isStop) {
      val len = is.read(buf, 0, buf.length);
      if (len == -1) isStop = true
      else os.write(buf, 0, len)
    }
  }

  def read(is: InputStream, encoding: String): String = {
    var resBytes: Array[Byte] = read(is)
    return new String(resBytes, encoding)
  }

  def read(is: InputStream): Array[Byte] = {
    var baos: ByteArrayOutputStream = new ByteArrayOutputStream(BYTE_BLOCK_LENGTH)
    copy(is, baos)
    baos.flush
    var resBytes: Array[Byte] = baos.toByteArray
    is.close
    baos.close
    return resBytes
  }
}

object EchoClient {
  def main(args: Array[String]): Unit = {
    val ip = if (args.length > 1 && args(0) != null) args(0) else "127.0.0.1";
    val port = if (args.length > 2 && args(1) != null) args(1).toInt else 8080
    val n = if (args.length > 3 && args(2) != null) args(2).toInt else 100
    val isReuseAddr = if (args.length > 4 && args(3) != null) args(3).toBoolean else false

    for (i <- 0 until n) {
      val socket = createSocket(ip, port, isReuseAddr)
      val msg = "hello"
      println("send " + msg + " to " + socket.getRemoteSocketAddress)
      val is = socket.getInputStream()
      val os = socket.getOutputStream()
      os.write(msg.getBytes("UTF-8"))
      os.flush()
      IO.read(is)
      is.close
      os.close
      socket.close
    }


  }

  private def createSocket(ip: String, port: Int, isReuseAddr: Boolean): Socket = {
    val socket = new Socket()
    socket.setReuseAddress(isReuseAddr)
    socket.connect(new InetSocketAddress(ip, port))
    return socket;
  }
}

Когда EchoClient был запущен после запуска EchoServer, EchoServer блокируется на IO.read(is) ,, если я закрываю EchoClient, EchoServer жалуется:

scala.actors.Actor$$anon$1@1dd46f7: caught java.net.SocketException: Connection reset
java.net.SocketException: Connection reset
    at java.net.SocketInputStream.read(SocketInputStream.java:168)
    at socket.echo.IO$.copy(Echo.scala:61)
    at socket.echo.IO$.read(Echo.scala:74)
    at socket.echo.EchoServer$$anonfun$act$1.apply$mcV$sp(Echo.scala:34)
    at scala.actors.Actor$$anon$1.act(Actor.scala:133)
    at scala.actors.Reactor$$anonfun$dostart$1.apply(Reactor.scala:222)
    at scala.actors.Reactor$$anonfun$dostart$1.apply(Reactor.scala:222)
    at scala.actors.ReactorTask.run(ReactorTask.scala:33)
    at scala.concurrent.forkjoin.ForkJoinPool$AdaptedRunnable.exec(ForkJoinPool.java:611)
    at scala.concurrent.forkjoin.ForkJoinTask.quietlyExec(ForkJoinTask.java:422)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.mainLoop(ForkJoinWorkerThread.java:340)
    at scala.concurrent.forkjoin.ForkJoinWorkerThread.run(ForkJoinWorkerThread.java:325)

Что-то не так в моем коде?

PS: пример кода написан на Scala, но я думаю, что это легко понять программистам Java

1 Ответ

0 голосов
/ 04 ноября 2011

Поскольку ваш клиент блокирует чтение отраженного ответа, основной вопрос заключается в том, действительно ли ваш сервер отображает все, что вы читаете. Ваш код ввода / вывода слишком сложен для этой простой задачи. Нет необходимости ни в ByteArrayOutputStreams, ни в преобразовании в строки и т. Д. Просто читайте и записывайте байты, следя за тем, чтобы записывалось только количество прочитанных байтов. «Сброс соединения» обычно означает, что вы записали соединение, которое уже было закрыто другим концом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...