请谨慎使用 avaliable 方法来申请缓冲区
2021-01-26 19:56
309 查看
问题
今天开始尝试用 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 来做,如果过了一段时间还没有读入数据,那就不读了。比较稳妥的方法是,在请求头里面写好长度,这样就能知道要读多少了。
相关文章推荐
- Java网络编程从入门到精通(34):读写缓冲区中的数据---使用get和put方法按顺序读写单个数据
- Google Maps API Key申请方法及地址(谷歌地图使用时的Key申请)
- Java网络编程从入门到精通(34):读写缓冲区中的数据---使用get和put方法按顺序读写单个数据
- 2017年的Microsoft Imagine Cup提供的免费Azure申请及使用方法
- 在并行方法体中谨慎使用锁
- C语言中动态的申请二(三)及多维数组的使用方法及释放方法
- 记录1年免费亚马逊AWS云服务器申请方法过程及使用技巧
- Google Maps API Key申请方法及地址(谷歌地图使用时的Key申请)
- JAVA基础学习之流的简述及演示案例、用缓冲区方法buffer读写文件、File类对象的使用、Serializable标记接口(6)
- 2015070304 - EffactiveJava笔记 - 第54条 谨慎使用本地方法
- IO:*使用缓冲区数组。 *使用就是可以操作数组的读写方法。
- 使用JS获取当前地理位置方法汇总(如用谷歌接口,会出再以上报错,必须申请密钥并设置接受服务器IP!!!)
- SEI-CERT Java编程规范(Thread Apis)-谨慎使用ThreadGroup提供的方法
- 为什么阿里巴巴要求谨慎使用ArrayList中的subList方法
- 黑马程序员--谨慎使用for循环中的remove(int index)方法
- 申请.TK域名,并使用DNSPOD解析的方法
- 把BufferedWriter和OutputStreamWriter连接起来时 注意最后需要使用flush()方法,以强制清空缓冲区中的剩余内容,防止遗露,
- 谨慎使用SocketChannel的read方法
- 聊聊C++临时对象的析构时间点------顺便再次提醒大家谨慎使用string的c_str方法
- Asp.net中static变量和viewstate的使用方法(谨慎)