Nanohttpd 是一款轻量型的java服务端框架。

github为https://github.com/NanoHttpd/nanohttpd

在集成使用到android上时,在日志中,反复会出现

03-14 17:28:25.858 E/StrictMode( 2530): java.lang.Throwable: Explicit termination method 'end' not called
03-14 17:28:25.858 E/StrictMode( 2530):     at dalvik.system.CloseGuard.open(CloseGuard.java:184)
03-14 17:28:25.858 E/StrictMode( 2530):     at java.util.zip.Deflater.<init>(Deflater.java:192)
03-14 17:28:25.858 E/StrictMode( 2530):     at java.util.zip.GZIPOutputStream.<init>(GZIPOutputStream.java:81)
03-14 17:28:25.858 E/StrictMode( 2530):     at java.util.zip.GZIPOutputStream.<init>(GZIPOutputStream.java:54)
03-14 17:28:25.858 E/StrictMode( 2530):     at org.nanohttpd.protocols.http.response.Response.sendBodyWithCorrectEncoding(Response.java:308)
03-14 17:28:25.858 E/StrictMode( 2530):     at org.nanohttpd.protocols.http.response.Response.sendBodyWithCorrectTransferAndEncoding(Response.java:299)
03-14 17:28:25.858 E/StrictMode( 2530):     at org.nanohttpd.protocols.http.response.Response.send(Response.java:268)
03-14 17:28:25.858 E/StrictMode( 2530):     at org.nanohttpd.protocols.http.HTTPSession.execute(HTTPSession.java:435)
03-14 17:28:25.858 E/StrictMode( 2530):     at org.nanohttpd.protocols.http.ClientHandler.run(ClientHandler.java:75)
03-14 17:28:25.858 E/StrictMode( 2530):     at java.lang.Thread.run(Thread.java:818)

原本没有奔溃,没有太在意,但是发现有点频繁,所以还是决定解决。在浏览了github上的讨论,有人提出这个问题,但是貌似没有人解决,于是自己下载源码,亲自修改源码解决

根源相对来说也明显:没有正常关闭流(绿色为我修改,红色为问题代码,紫色是其它修改)

org.nanohttpd.protocols.http.response.Response

    /*** Sends given response to the socket.*/public OutputStream send(OutputStream outputStream) {SimpleDateFormat gmtFrmt = new SimpleDateFormat("E, d MMM yyyy HH:mm:ss 'GMT'", Locale.getDefault());gmtFrmt.setTimeZone(TimeZone.getTimeZone("GMT"));try {if (this.status == null) {throw new Error("sendResponse(): Status can't be null.");}PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(outputStream, new ContentType(this.mimeType).getEncoding())), false);pw.append("HTTP/1.1 ").append(this.status.getDescription()).append(" \r\n");if (this.mimeType != null) {printHeader(pw, "Content-Type", this.mimeType);}if (getHeader("date") == null) {printHeader(pw, "Date", gmtFrmt.format(new Date()));}for (Entry<String, String> entry : this.header.entrySet()) {printHeader(pw, entry.getKey(), entry.getValue());}for (String cookieHeader : this.cookieHeaders) {printHeader(pw, "Set-Cookie", cookieHeader);}if (getHeader("connection") == null) {printHeader(pw, "Connection", (this.keepAlive ? "keep-alive" : "close"));}if (getHeader("content-length") != null) {setUseGzip(false);}if (useGzipWhenAccepted()) {printHeader(pw, "Content-Encoding", "gzip");setChunkedTransfer(true);}long pending = this.data != null ? this.contentLength : 0;if (this.requestMethod != Method.HEAD && this.chunkedTransfer) {printHeader(pw, "Transfer-Encoding", "chunked");} else if (!useGzipWhenAccepted()) {pending = sendContentLengthHeaderIfNotAlreadyPresent(pw, pending);}pw.append("\r\n");pw.flush();OutputStream end = sendBodyWithCorrectTransferAndEncoding(outputStream, pending);outputStream.flush();NanoHTTPD.safeClose(this.data);return end;} catch (IOException ioe) {NanoHTTPD.LOG.log(Level.SEVERE, "Could not send response to the client", ioe);}return outputStream;}
    private OutputStream sendBodyWithCorrectTransferAndEncoding(OutputStream outputStream, long pending) throws IOException {if (this.requestMethod != Method.HEAD && this.chunkedTransfer) {ChunkedOutputStream chunkedOutputStream = new ChunkedOutputStream(outputStream);OutputStream end = sendBodyWithCorrectEncoding(chunkedOutputStream, -1);chunkedOutputStream.finish();return end;} else {return sendBodyWithCorrectEncoding(outputStream, pending);}}private OutputStream sendBodyWithCorrectEncoding(OutputStream outputStream, long pending) throws IOException {if (useGzipWhenAccepted()) {GZIPOutputStream gzipOutputStream = new GZIPOutputStream(outputStream);sendBody(gzipOutputStream, -1);gzipOutputStream.finish();return gzipOutputStream;} else {sendBody(outputStream, pending);return outputStream;}}

以上,对于传入的流,作者对其进行了两次封装,并调用了finish方法,之后在HTTPSession中,最后会统一用NanoHTTPD.safeClose()进行关闭。但是,作者明显是漏了对于GZIPOutputStream的关闭,需要对其进行close调用。但是,直接在finish后面调用close不太合适,如果集成了websocket模块后,就会发现作者对管道之后还有用,所以按着作者的思路,我把最后生成的流又return回去,在整个程序的最后进行关闭。

org.nanohttpd.protocols.http.HTTPSession

    @Overridepublic void execute() throws IOException {Response r = null;try {// Read the first 8192 bytes.// The full header should fit in here.// Apache's default header limit is 8KB.// Do NOT assume that a single read will get the entire header// at once!byte[] buf = new byte[HTTPSession.BUFSIZE];this.splitbyte = 0;this.rlen = 0;int read = -1;this.inputStream.mark(HTTPSession.BUFSIZE);try {read = this.inputStream.read(buf, 0, HTTPSession.BUFSIZE);} catch (SSLException e) {throw e;} catch (IOException e) {NanoHTTPD.safeClose(this.inputStream);NanoHTTPD.safeClose(this.outputStream);throw new SocketException("NanoHttpd Shutdown");}if (read == -1) {// socket was been closedNanoHTTPD.safeClose(this.inputStream);NanoHTTPD.safeClose(this.outputStream);throw new SocketException("NanoHttpd Shutdown");}while (read > 0) {this.rlen += read;this.splitbyte = findHeaderEnd(buf, this.rlen);if (this.splitbyte > 0) {break;}read = this.inputStream.read(buf, this.rlen, HTTPSession.BUFSIZE - this.rlen);}if (this.splitbyte < this.rlen) {this.inputStream.reset();this.inputStream.skip(this.splitbyte);}this.parms = new HashMap<String, List<String>>();if (null == this.headers) {this.headers = new HashMap<String, String>();} else {this.headers.clear();}// Create a BufferedReader for parsing the header.BufferedReader hin = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(buf, 0, this.rlen)));// Decode the header into parms and header java propertiesMap<String, String> pre = new HashMap<String, String>();decodeHeader(hin, pre, this.parms, this.headers);if (null != this.remoteIp) {this.headers.put("remote-addr", this.remoteIp);this.headers.put("http-client-ip", this.remoteIp);}this.method = Method.lookup(pre.get("method"));if (this.method == null) {throw new ResponseException(Status.BAD_REQUEST, "BAD REQUEST: Syntax error. HTTP verb " + pre.get("method") + " unhandled.");}this.uri = pre.get("uri");this.cookies = new CookieHandler(this.headers);String connection = this.headers.get("connection");boolean keepAlive = "HTTP/1.1".equals(protocolVersion) && (connection == null || !connection.matches("(?i).*close.*"));// Ok, now do the serve()// TODO: long body_size = getBodySize();// TODO: long pos_before_serve = this.inputStream.totalRead()// (requires implementation for totalRead())r = httpd.handle(this);// TODO: this.inputStream.skip(body_size -// (this.inputStream.totalRead() - pos_before_serve))if (r == null) {throw new ResponseException(Status.INTERNAL_ERROR, "SERVER INTERNAL ERROR: Serve() returned a null response.");} else {String acceptEncoding = this.headers.get("accept-encoding");this.cookies.unloadQueue(r);r.setRequestMethod(this.method);if (acceptEncoding == null || !acceptEncoding.contains("gzip")) {r.setUseGzip(false);}r.setKeepAlive(keepAlive);OutputStream end = r.send(this.outputStream);end.close();}if (!keepAlive || r.isCloseConnection()) {throw new SocketException("NanoHttpd Shutdown");}} catch (SocketException e) {// throw it out to close socket object (finalAccept)throw e;} catch (SocketTimeoutException ste) {// treat socket timeouts the same way we treat socket exceptions// i.e. close the stream & finalAccept object by throwing the// exception up the call stack.throw ste;} catch (SSLException ssle) {//Response resp = Response.newFixedLengthResponse(Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SSL PROTOCOL FAILURE: " + ssle.getMessage());//resp.send(this.outputStream);NanoHTTPD.safeClose(this.outputStream);} catch (IOException ioe) {//Response resp = Response.newFixedLengthResponse(Status.INTERNAL_ERROR, NanoHTTPD.MIME_PLAINTEXT, "SERVER INTERNAL ERROR: IOException: " + ioe.getMessage());//resp.send(this.outputStream);NanoHTTPD.safeClose(this.outputStream);} catch (ResponseException re) {//Response resp = Response.newFixedLengthResponse(re.getStatus(), NanoHTTPD.MIME_PLAINTEXT, re.getMessage());//resp.send(this.outputStream);NanoHTTPD.safeClose(this.outputStream);} finally {NanoHTTPD.safeClose(r);this.tempFileManager.clear();}}

如此修改(不知道有没有漏掉),目前没有发现再报此问题。至于紫色的部分,我个人觉得不合理,在端口已经异常的情况下,我认为不用再发消息,只会导致循环报错。

Nanohttpd 异常 Explicit termination medthod 'end' not called 解决方法相关推荐

  1. win10任务栏图标显示异常(重启资源管理器无果)解决方法

    win10任务栏图标显示异常(重启资源管理器无果)解决方法 方法1: - Ctrl+Win+R打开任务管理器 - 点击[文件],点击[运行新任务],输入[Explorer],运行,此刻可以看到Wind ...

  2. explicit type is missing (int assumed)解决方法

    用KEIL MDK5.X版本开发STM32程序的时候,有时候使用的代码是从网上下载的, 编译会报这个错误 :explicit type is missing ("int" assu ...

  3. win 7计算机图标变了,Win7系统桌面图标显示异常统一变成白色的两种解决方法

    Win7系统桌面图标显示异常统一变成白色,如下图所示: Win7系统桌面图标显示异常统一变成白色的两种解决方法: 解决方法一:更改主题 1.右键单击桌面空白处--个性化,随意更改一个主题即可(Win7 ...

  4. c# 无法加载 DLL xxxxxxxx找不到指定的模块。 (异常来自HRESULT:0x8007007E)。的一个解决方法

    c# 无法加载 DLL xxxxxxxx找不到指定的模块. (异常来自HRESULT:0x8007007E).的一个解决方法 参考文章: (1)c# 无法加载 DLL xxxxxxxx找不到指定的模块 ...

  5. 使用enterTextInWebElement处理qq授权页报“网络异常,请稍后再试”的解决方法

    robotium4.0之后支持处理WebElement,从此第三方的web页有更简单的解决方法. 上周五我很愉快的处理完新浪微博和腾讯微博的授权页之后,这周一处理qq的授权页,发现使用robotium ...

  6. 微信小程序网络请求异常怎么办_微信小程序打开提示“网络异常,请检查网络状态”的解决方法...

    症状:打开微信小程序的时候,提示"网络异常,请检查网络状态",无法加载数据. 问题客户端:安卓手机 经过测试:IOS和微信桌面版,均正常. 唯独安卓手机不行,如下图所示,这个问题不 ...

  7. VS2010调试时出现“0x7556d36f 处最可能的异常: 0x000006BA: RPC 服务器不可用”的解决方法

    现象:1.在使用Visual Studio 2010 c++调试程序时,无法使用文件对话框打开文件,只要执行打开文件对话框,就报"0x7556d36f 处最可能的异常: 0x000006BA ...

  8. 康佳电视显示服务器连接异常,康佳电视五大常见故障及解决方法

    ​首页文章列表系统知识正文 康佳电视常见故障--五大常见故障以及解决方法介绍 2016-10-30 22:13:53 16546 电视在使用过程中,也是会经常出现这样那样的问题.康佳电视也不会例外.很 ...

  9. php 0x80070002,vs2015 系统找不到指定的文件(异常来自HRESULT:0x80070002)问题的解决方法...

    vs2015 创建mvc项目时,弹出错误信息内容(系统找不到指定的文件(异常来自HRESULT:0x80070002)) 弹出窗体如下图所示: 导致整个原因是:未安装NuGet包 解决方法: 1)打开 ...

  10. 百度云盘上传显示服务器异常,百度网盘常见问题之网络异常,这里有最全面的解决方法...

    很多人都会选择用百度网盘来存放资料或者下载文件.但是很多用户最近都反映一个问题,就是自己在登录的时候或者在下载文件的时候,百度网盘会提示网络异常.那么,百度网盘网络异常怎么办?为了帮助用户们更愉快地使 ...

最新文章

  1. java虚拟机内存分为,深入理解Java虚拟机笔记(一)----内存划分
  2. sdut-oj-4205-寻找关键点
  3. LeetCode-461. 汉明距离(python3)
  4. Vulnhub靶机渗透之 RAVEN: 1
  5. 索佳电子水准数据传输软件_183家软件服务行业上市公司完整名单及分析
  6. ida调试linux程序,MAC使用IDA PRO远程调试LINUX程序
  7. 简单讲述一下Intent的传值过程
  8. 必看总结!深度学习时代您应该阅读的10篇文章了解图像分类!
  9. 搜索引擎的那些事(网页下载)
  10. Spring好处—总结
  11. 一次新生代民工工友切磋经历
  12. python怎么引入os模块的函数_Python之OS模块函数
  13. JAVA JDK 官网安装包启动后没反应
  14. 基于SpringBoot的个人博客系统【完整项目源码】
  15. 联通光纤服务器没有响应怎么办,联通网速不稳定(联通光纤不稳定解决方法)
  16. python词云图片生成不出来_python实现使用词云展示图片
  17. 如何免费将XPS转换为PDF格式
  18. opencv经过canny生成的视频无法播放问题的解决方法
  19. bzoj 2101: [Usaco2010 Dec]Treasure Chest 藏宝箱【区间dp】
  20. 北京亚控笔试题目(2014年10月9日)

热门文章

  1. 猿创征文|工具在手,天下我有(初入职场必备的黑科技工具)
  2. 多智能体强化学习(一) IQL、VDN、QMIX、QTRAN算法详解
  3. MT4MT5跟单EA系统跨平台
  4. 初学Power bi项目财务与人力/利润表/人员结构-刘刘的第一篇学习记录文章
  5. 一个工业相机通用类解决大部分业内流行相机的访问(基于大华相机的动态链接库开发的通用相机类)C#版
  6. java 发卡平台支付_基于jsp的自动发卡平台-JavaEE实现自动发卡平台 - java项目源码...
  7. nrf52840 spi 32MHz配置
  8. OBS录制的时候黑屏怎么办
  9. HCIE 习题整理 含解释
  10. 计算机网络毕业论文格式模板范文,计算机网络论文范文 计算机网络方面有关毕业论文的格式范文2万字...