The java.io.IOException in netty #34

Closed
yubingxing opened this Issue Aug 20, 2012 · 13 comments

Comments

Projects
None yet
2 participants

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]

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

Owner

veebs commented Aug 21, 2012

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?

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.

Owner

veebs commented Aug 23, 2012

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.

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:

<appender name="FILE" class="ch.qos.logback.core.FileAppender">
    <file>log/notifier.log</file>

    <layout class="ch.qos.logback.classic.PatternLayout">
        <Pattern>%date %level [%thread] %logger{10} [%file:%line] %msg%n
        </Pattern>
    </layout>
</appender>

<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <encoder>
        <pattern>%d{HH:mm:ss.SSS} [%thread] [%X{sourceThread}] %-5level
            %logger{36} %X{akkaSource} - %msg%n</pattern>
    </encoder>
</appender>

<appender name="WEBLOG"
    class="ch.qos.logback.core.rolling.RollingFileAppender">
    <file>log/apnWebLogFile.log</file>
    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
        <!-- daily rollover -->
        <fileNamePattern>log/apnWebLogFile.%d{yyyy-MM-dd}.log</fileNamePattern>

        <!-- keey 30 days' worth of history -->
        <maxHistory>30</maxHistory>
    </rollingPolicy>
    <encoder>
        <pattern>%msg%n</pattern>
    </encoder>
</appender>

<logger name="org.mashupbots.socko.infrastructure.WebLogWriter"
    level="info" additivity="false">
    <appender-ref ref="WEBLOG" />
</logger>

<root level="info">
    <appender-ref ref="STDOUT" />
    <!-- <appender-ref ref="FILE" /> -->
</root>
Owner

veebs commented Aug 23, 2012

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

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)
  }
}
Owner

veebs commented Aug 23, 2012

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

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

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.

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.

Owner

veebs commented Aug 23, 2012

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.

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

veebs closed this Aug 25, 2012

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment