为什么com.sun.net.httpserver.HttpServer挂起?

时间:2013-03-02 11:03:53

标签: java https hang

当我使用com.sun.net.httpserver.HttpServer实现的简单HTTPS服务器通过this PHP proxy(使用curl)调用时,它可以正常工作。但是,一旦我不使用代理但更改我的Web表单以便浏览器直接将其请求发送到服务器,服务器就会变得不稳定,有时会停止响应。然后客户端将等待响应,直到超时。这个问题难以重现,有时会在实时系统中发生。所有这些都是通过HTTPS,在非标准端口(目前为8081)。我的服务器返回XML。

我在服务器不再响应时看到的堆栈跟踪(通过“kill -QUIT [pid]”):

"Thread-2" prio=10 tid=0x0000000017fc4800 nid=0x1c2b runnable
    [0x00002ba5ec97c000]
java.lang.Thread.State: RUNNABLE
at sun.nio.ch.FileDispatcherImpl.read0(Native Method)
at sun.nio.ch.SocketDispatcher.read(SocketDispatcher.java:39)
at sun.nio.ch.IOUtil.readIntoNativeBuffer(IOUtil.java:218)
at sun.nio.ch.IOUtil.read(IOUtil.java:191)
at sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:359)
    - locked <0x00000000fd1e4b98> (a java.lang.Object)
at sun.net.httpserver.SSLStreams$EngineWrapper.recvAndUnwrap(SSLStreams.java:334)
    - locked <0x00000000fd1e4c58> (a java.lang.Object)
at sun.net.httpserver.SSLStreams.recvData(SSLStreams.java:409)
at sun.net.httpserver.SSLStreams$InputStream.read(SSLStreams.java:524)
at sun.net.httpserver.SSLStreams$InputStream.read(SSLStreams.java:593)
at sun.net.httpserver.Request.readLine(Request.java:84)
at sun.net.httpserver.Request.<init>(Request.java:54)
at sun.net.httpserver.ServerImpl$Exchange.run(ServerImpl.java:529)
at sun.net.httpserver.ServerImpl$DefaultExecutor.execute(ServerImpl.java:156)
at sun.net.httpserver.ServerImpl$Dispatcher.handle(ServerImpl.java:424)
at sun.net.httpserver.ServerImpl$Dispatcher.run(ServerImpl.java:389)
at java.lang.Thread.run(Thread.java:722)

我已尝试过的内容:发送Connection: close http标头 - 没有帮助。编写一个使用多个线程并行查询服务器的Java测试用例 - 工作正常。

所以问题是:浏览器与我的代理有什么不同,为什么这会让我的服务器进程挂起?

来源:此处为the source of the HttpHandler,此处为the source of the Server that uses that handler

后台:我希望任何人都可以在他们的网页上使用我的REST服务,而无需安装代理(需要绕过Javascript跨域策略)。为此,服务器发送Access-Control-Allow-Origin: *标头。与Jetty或Tomcat Embedded相比,我使用Java提供的类具有最小的开销。

1 个答案:

答案 0 :(得分:6)

为什么代理和&amp;的不同行为没有代理?

  • 更多没有代理的连接
  • 真实世界的浏览器用户可以做有趣的事情,比如启动请求然后取消/返回按钮/新请求。

您需要设置套接字超时。遗憾的是,API文档建议无法以编程方式执行此操作。

但你可以设置resquest&amp;通过JVM系统属性响应超时:

http://www.javaworld.com/community/node/8424
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/7-b147/sun/net/httpserver/ServerConfig.java
http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6563368

设置这些系统属性:

sun.net.httpserver.clockTick 默认值= 10000,即10秒

sun.net.httpserver.timerMillis 默认值= 1000,即1秒

sun.net.httpserver.maxReqTime 默认值= -1即永远。

默认&gt; 0给出timeout = default *(clockTick ot timerMillis)sec

sun.net.httpserver.maxRspTime 默认值= -1即永远。

默认&gt; 0给出timeout = default *(clockTick ot timerMillis)sec


显然,在你的HttpHandler.handle()方法中,确保在响应头中设置响应代码:

  httpExchange.sendResponseHeaders(HttpURLConnection.HTTP_OK, response.length());  
  final OutputStream os = httpExchange.getResponseBody();  
  os.write( response.getBytes() );  
  os.close();