问题

今天开始尝试用 Java 写 http 服务器,开局就遇到 Bug。

我先写了一个多线程的、BIO 的 http 服务器,其中接收请求的部分,会将请求的第一行打印出来。

下面是浏览器发出的请求和控制台的输出情况。我们竟然收到了一个空的请求!!这是为什么呢?

我解析请求的部分代码如下。

// request
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] buffer = new byte[bis.available()];
int len = bis.read(buffer);
String firstLine = new String(buffer).split("\n")[0];
System.out.println("".equals(firstLine) ? "EMPTY" : firstLine);

这是为什么呢?我们先打个断点看看是个什么状况。

刷新浏览器,重新请求一下试试。惊奇的发现,bug 消失了。。

如果把断点打在后面几行,bug 又出现了。

emmm,太迷了。

分析

我们仔细看看上面第二个断点的截图,我们会发现 buffer 的值为 {},这意味着申请的空间是 0!这就意味着 available 返回的是 0。

这个函数的注释中写到,返回一个可以被读取的字节数的估计值。这个估计值并不是实际的长度,在网络请求中,这个值有可能是 0,因此,我们申请的空间就是 0,之后调用 read 方法自然也读不到任何东西。

调用链是这样子的:

解决方法

我们自己开一个固定大小的缓冲区,然后读取就好了,read 方法会阻塞直到数据流进来。

// request
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());
byte[] buffer = new byte[BUFFER_SIZE];
int len = bis.read(buffer);
System.out.println(new String(buffer).split("\n")[0]);

那这个方法就没有问题了吗?其实还是有问题的,比如 POST 提交文件的时候,显然文件的大小并不是只有 BUFFER_SIZE 那么小而已。我们还需要想办法来获取一个未知长度的 InputStream。未知长度的处理方法,可以使用 timeout 来做,如果过了一段时间还没有读入数据,那就不读了。比较稳妥的方法是,在请求头里面写好长度,这样就能知道要读多少了。

最新文章

  1. nginx反向代理+集群
  2. tool list
  3. 十步让 WebForm项目 变为 Mvc项目
  4. U6会计科目导入致对账不平
  5. linux命令行后台运行与调回
  6. 前端MVVM框架avalon - 模型转换1
  7. CentOS 7 安装 Nginx 反向代理 node
  8. Java KeyTool command
  9. Spring的声明式事务管理
  10. 树pao(雾)
  11. Count(广工14届竞赛)
  12. Lua程序设计(三)面向对象实现一个简单的类
  13. pyDay4
  14. 《剑指offer》第二十五题(合并两个排序的链表)
  15. linux yum 下载至本地及使用本地缓存安装包
  16. 传统项目利用Hystrix实现热点接口的服务隔离
  17. Eclipse在线安装hibernate tools插件
  18. 类似hibernate实现sql增删改错
  19. 完成了C++作业,本博客现在开始全面记录acm学习历程,真正的acm之路,现在开始
  20. Codeforces Round #499 (Div. 2)(1011)

热门文章

  1. svn add . 报错,不能add全部,因为有一些文件已经在版本库中了
  2. 弱肉强食——《哆啦A梦:大雄的新恐龙》观后感
  3. 不一样的资产安全 3D 可视化平台
  4. Java基础进阶:学生管理系统数组方式分包源码实现,教师管理系统集合和数组两种方式源码实现,图书馆管理系统源码实现,现附重难点,代码实现源码,课堂笔记,课后扩展及答案
  5. [.NET] - 基础知识 - 如何debug一个.NET application
  6. 容器编排系统K8s之StatefulSet控制器
  7. [leetcode]355. Design Twitter设计实现一个微博系统
  8. Mac苹果电脑单片机开发
  9. web前台界面的两种验证方式
  10. 熬夜肝了一周!总结了这套对标阿里P8的java秘籍,限时发布3天!