关于Java http服务器构建中收不到浏览器get请求的解决方案。
背景:
前几天心血来潮,想自己实现一个http服务器,我兴致勃勃地写完了处理get请求的方法,但是也发现了一个比较奇怪的现象。
现象描述:
在浏览器中输入 127.0.0.1/index.html 时,页面成功显示并不总是成功的,在后台控制台监控发现,服务器有时候会无法接受到get请求。
这下子本菜鸟,直接懵逼了,d了好久的bug都没有发现······· 为什么会出现后端服务器接受不了请求的情况呢?
在我搜寻了多方的资料以及苦逼的bug过后,终于发现了其中的奥妙。
原因在于这个代码:
int size = stream.available() ;
这串代码有什么用呢? 大家可以看一下我以下的代码:
int size = stream.available() ;
System.out.println("request:");
while(size--!=0){
b = stream.read() ;
System.out.print((char)b);
requestBuffer.append((char)b) ;
}
很明显,我这里调用了available方法获得了inputstream中可以读取的数据的规模,也就是get请求中的headers数据大小。我通过size控制循环读取里面的字符。
问题就出在这。
avaliable方法不是万能的。
我们对avaliable的简单印象就是 他返回的是 socket.getInputStream中能够被读取的数据,但是对于网络流来说,该方法返回0,并不意味着对方发送的流中无数据可读。
原因:网络之间的通讯是间断性的,一串字节往往分几批来进行发送,所以调用avaliable方法返回的数值长度是不唯一的,大部分情况之下是0。
这就是我们出现的问题所在。
解决方案:
在调用avaliable方法之前,调用read方法,确保能接收到数据,然后再调用avaliable方法,总长度就是avaliable + 1。具体看以下代码。
int b = 0 ;
StringBuffer requestBuffer = new StringBuffer() ;
b = stream.read() ;
requestBuffer.append((char)b) ;
int size = stream.available() ;
System.out.println("request:");
while(size--!=0){
b = stream.read() ;
System.out.print((char)b);
requestBuffer.append((char)b) ;
}
至此,问题solved! 如果您想搞清楚深层原理的话,可以看一下这个大佬的博客: https://www.cnblogs.com/zjfjava/p/10829241.html 感谢您的阅读!欢迎您的指教!
|