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. 设计一个user类(Java)
  2. Windows内核新手上路2——挂钩shadow SSDT
  3. Al芯片前景看好,市场规模在2023年将达343亿美元
  4. 前端学习(2507):初始化多个实例化对象
  5. java集合数组,数组小到大排序,数组大到小排序
  6. CS224n学习笔记1-nlp介绍和词向量
  7. Python网络请求库Requests,妈妈再也不会担心我的网络请求了(二)
  8. mysql debug log_PHP代码调试与日志
  9. java接口构造函数_Java8自定义函数式编程接口和便捷的引用类的构造器及方法
  10. ES11新特性_Promise.allSettled---JavaScript_ECMAScript_ES6-ES11新特性工作笔记062
  11. 深蓝-视觉slam-第三节习题
  12. 【informix】informix 日期字段
  13. Verilog实现之任意分频电路
  14. FILTER的使用与过滤器实现session登录案例
  15. web3.js的provider
  16. LU分解(matlab实现)
  17. 纯CSS打气球爆炸js特效
  18. oracle如何查看pdb,Oracle基础操作——CDB-PDB
  19. php是根据html中的值查询数据条件_html显示php返回的数据
  20. 压力测试工具ab介绍

热门文章

  1. STM32F1与STM32CubeIDE编程实例-光敏电阻(LDR)传感器驱动
  2. 自媒体内容采集工具,采集多个自媒体平台内容
  3. adb连接手机显示:List of devices attached
  4. python基本快捷键
  5. prelu()的 tf 代码
  6. 关于威联通升级5.0系统无法登录的解决办法(有用)
  7. 精英二代手柄测试软件,微软精英手柄2代评测 继续引领行业标准
  8. 将图片url转换成 BufferedImage
  9. 项目经理是有责无权的“领导” 要会借力
  10. linux下仓库管理系统,[源码和文档分享]基于Linux的仓库管理系统