mashupbots / socko

A Scala web server powered by Netty networking and AKKA processing.
Other
255 stars 51 forks source link

The java.io.IOException in netty #34

Closed yubingxing closed 12 years ago

yubingxing commented 12 years ago

2012-08-16 17:29:34,187 ERROR [New I/O worker #1] o.m.s.w.RequestHandler [RequestHandler.scala:182] Exception caught in HttpRequestHandler java.io.IOException: Connection reset by peer at sun.nio.ch.FileDispatcherImpl.read0(Native Method) ~[na:1.7.0] at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39) ~[na:1.7.0] at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:218) ~[na:1.7.0] at sun.nio.ch.IOUtil.read(IOUtil.java:186) ~[na:1.7.0] at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:359) ~[na:1.7.0] at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:63) ~[netty-3.5.3.Final.jar:na] at org.jboss.netty.channel.socket.nio.AbstractNioWorker.processSelectedKeys(AbstractNioWorker.java:385) ~[netty-3.5.3.Final.jar:na] at org.jboss.netty.channel.socket.nio.AbstractNioWorker.run(AbstractNioWorker.java:256) ~[netty-3.5.3.Final.jar:na] at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:35) ~[netty-3.5.3.Final.jar:na] at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110) [na:1.7.0] at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603) [na:1.7.0] at java.lang.Thread.run(Thread.java:722) [na:1.7.0]

yubingxing commented 12 years ago

I had open logger to report the web notification info and exceptions, if this would cause the IOException ?

veebs commented 12 years ago

Hi, sorry for the slow response. GitHub notifications did not send me my notification emails. I'll have to checkout my settings!

java.io.IOException: Connection reset by peer

I think you client maybe closing the connection. Which client are you using? What are you trying implement?

yubingxing commented 12 years ago

Hi, thank you for your response. I use the flash client to connect the server for uploading files, but the client doesn't receive any response, if I use html to upload file, it work fine.

veebs commented 12 years ago

Have u tried using the latest socko 0.2.1? It has a later version of Netty which may fix the problem? Is there any way to debug the flash client because it seems, from the error, that the flash client is closing the connection for some reason.

yubingxing commented 12 years ago

Yes, I was used the latest socko version 0.2.1, but the exception not only when useing the flash client to upload files, some normal http request would caught that exception, I only open the logger to trace the event. My logback.xml is like this: <?xml version="1.0" encoding="UTF-8"?>

``` log/notifier.log %date %level [%thread] %logger{10} [%file:%line] %msg%n %d{HH:mm:ss.SSS} [%thread] [%X{sourceThread}] %-5level %logger{36} %X{akkaSource} - %msg%n log/apnWebLogFile.log log/apnWebLogFile.%d{yyyy-MM-dd}.log 30 %msg%n ```
veebs commented 12 years ago

Can you try to file upload using netty. Here's the file upload example program: https://github.com/netty/netty/tree/3/src/main/java/org/jboss/netty/example/http/upload.

Not sure why you are getting a "java.io.IOException: Connection reset by peer" error. I cannot reproduce it. How big a file are you uploading? Also, are you using the socko file upload example app? If not, can you upload your code.

Thanks

yubingxing commented 12 years ago
object HttpServer extends Logger {
  private val actorConfig = """
    my-pinned-dispatcher {
      type=PinnedDispatcher
      executor=thread-pool-executor
    }
    akka {
      event-handlers = ["akka.event.slf4j.Slf4jEventHandler"]
      loglevel=DEBUG
      actor {
        deployment {
          /static-file-router {
            router = round-robin
            nr-of-instances = 20
          }
          /file-upload-router {
            router = round-robin
            nr-of-instances = 10
          }
        }
      }
    }
    """
  private val actorSystem = ActorSystem("HttpServer", ConfigFactory.parseString(actorConfig))

  def apply() = {
    new HttpServer(actorSystem)
  }
}
class HttpServer private (val system: ActorSystem) extends AnyRef {

  private val conf = ConfigFactory.load

  // Create root, upload and temp dir
  private val rootDir: File = new File(conf.getString("HttpServer.rootPath"))
  rootDir mkdir
  private val uploadDir: File = new File(rootDir.getAbsoluteFile() + "/" + conf.getString("HttpServer.uploadPath"))
  uploadDir mkdir
  private var tempDir: File = new File(conf.getString("HttpServer.tmpPath"))
  tempDir mkdir;
  //  println("[rootFilePaths] = " + rootDir.getAbsolutePath)
  StaticContentHandlerConfig.rootFilePaths = Seq(rootDir.getAbsolutePath);
  StaticContentHandlerConfig.tempDir = tempDir;
  StaticContentHandlerConfig.browserCacheTimeoutSeconds = 60
  StaticContentHandlerConfig.serverCacheTimeoutSeconds = 2

  private val staticFileHandlerRouter = system.actorOf(Props[StaticContentHandler]
    .withRouter(FromConfig()).withDispatcher("my-pinned-dispatcher"), "static-file-router")

  private val fileUploadHandlerRouter = system.actorOf(Props[FileUploadHandler]
    .withRouter(FromConfig()).withDispatcher("my-pinned-dispatcher"), "file-upload-router")
  /**
   * define routes
   */
  private val routes = Routes({
    case HttpRequest(httpRequest) => httpRequest match {
      case POST(Path("/upload")) =>
        // Save file to the upload directory so it can be downloaded
        fileUploadHandlerRouter ! FileUploadRequest(httpRequest, uploadDir)
      case GET(Path("/")) =>
        httpRequest.response.redirect("http://" + httpRequest.endPoint.host + "/index.html")
      case GET(PathSegments(fileName :: Nil)) =>
        // Download requested file
        staticFileHandlerRouter ! new StaticFileRequest(httpRequest, new File(rootDir.getAbsolutePath, fileName))
      case GET(_) =>
        println("httpRequest = " + httpRequest.request)
        // Send request to HttpHandler
        system.actorOf(Props[HttpHandler]) ! httpRequest
    }
  })

  private val webServer: WebServer = new WebServer(new WebServerConfig(conf, "HttpServer"),
    routes, system)

  def start() {
    // Create content
    createContent(rootDir)

    // Start web server
    webServer start;
    Runtime.getRuntime().addShutdownHook(new Thread {
      override def run {
        webServer stop
      }
    })
    println("WebServer starting..., http://" + webServer.config.hostname + ":" + webServer.config.port + "/")
  }

  def stop() {
    webServer.stop()
    if (staticFileHandlerRouter != null) {
      system.stop(staticFileHandlerRouter)
    }
    if (fileUploadHandlerRouter != null) {
      system.stop(fileUploadHandlerRouter)
    }
    if (tempDir != null) {
      FileUtils.deleteDirectory(tempDir)
      tempDir = null
    }
    system.shutdown()
  }

    val indexFile = new File(dir, "index.html")
    val out = new FileOutputStream(indexFile)
    out.write(buf.toString().getBytes(CharsetUtil.UTF_8))
    out.close()

    buf.setLength(0)
    buf append "body { font-family: Arial,Helv,Courier,Serif}\n"
    buf append "div.field {margin-top: 20px;}\n"

    val cssFile = new File(dir, "mystyle.css")
    val out2 = new FileOutputStream(cssFile)
    out2.write(buf.toString().getBytes(CharsetUtil.UTF_8))
    out2.close()
  }
}

/**
 * Processes file uploads
 * @author IceStar
 */
private class FileUploadHandler extends Actor {
  private val log = Logging(context.system, this)

  def receive = {
    case msg: FileUploadRequest => {
      val ctx = msg.event
      try {
        val contentType = ctx.request.contentType
        if (contentType != "" &&
          (contentType.startsWith("multipart/form-data")) ||
          contentType.startsWith("application/x-www-form-urlencoded")) {
          val decoder = new HttpPostRequestDecoder(HttpDataFactory.value, ctx.nettyHttpRequest)

          val descriptionField = decoder.getBodyHttpData("fileDescription").asInstanceOf[Attribute]

          val uploadField = decoder.getBodyHttpData("fileUpload").asInstanceOf[FileUpload]
          val name = uploadField.getFilename
          var filename: String = null
          if (name.indexOf("/") < 0)
            filename = name.substring(name.lastIndexOf("\\") + 1)
          else
            filename = name.substring(name.lastIndexOf("/") + 1)
          val destFile = new File(msg.saveDir, filename)
          uploadField.renameTo(destFile)

          ctx.response.write("File \"" + filename + "\" upload complete!")
        } else {
          ctx.response.write(HttpResponseStatus.BAD_REQUEST)
        }
      } catch {
        case ex => {
          ctx.response.write(HttpResponseStatus.INTERNAL_SERVER_ERROR, ex.toString())
        }
      }
    }
  }
}

private case class FileUploadRequest(event: HttpRequestEvent, saveDir: File)

/**
 * Data factory for use with 'HttpPostRequestDecoder'
 * @author IceStar
 */
private object HttpDataFactory {
  val value = new DefaultHttpDataFactory(DefaultHttpDataFactory.MINSIZE)
}
private class HttpHandler extends Actor {
  def receive = {
    case event: HttpRequestEvent =>
      val response = event.response
      event match {
        case GET(PathSegments("token" :: appId :: tokenId :: Nil)) =>
          //receive from iphone/ipad device token
          RedisPool.hset(Server.TOKENS + appId, tokenId, true)
          response write "receive token OK"
        case GET(PathSegments("urls" :: appId :: lang :: Nil)) =>
          response write CommonUtils.getOrElse(RedisPool.hget(Server.URLS + appId, lang), "{\"lang\":\"" + lang + "\"}")
        case _ =>
          response write ("Hello from Socko (" + new Date().toString() + ")")
      }
      context.stop(self)
  }
}
veebs commented 12 years ago

Thanks for uploading your code. When during the upload process does your error appear? Does any code in FileUploadHandler get executed?

yubingxing commented 12 years ago

not only in upload process, I tried normal http request would also caught the IOException.

yubingxing commented 12 years ago

I use chrome to access the use "http://serveraddress/urls/appId/lang", can receive right response, but after few seconds the java.io.IOException would caught in HttpRequestHandler.

yubingxing commented 12 years ago

I think the exception would happen when the HttpRequestHandler receiving the request and logging in the logfile, then the file io was crashed and caught this exception.

veebs commented 12 years ago

Hi

So the file uploaded ok and you got a response from the server ? Then after a few seconds, the error appears?

If so, i think that this may be due to chrome closing the http connection with the server - hence the connection closed by peer error. I think it is normal.

Sent from my iPhone

On 23/08/2012, at 5:03 PM, IceStar notifications@github.com wrote:

I think the exception would happen when the HttpRequestHandler receiving the request and logging in the logfile, then the file io was crashed and caught this exception.

— Reply to this email directly or view it on GitHub.

yubingxing commented 12 years ago

Thank you for your response, I use the other browser like ie was also cause this.