一个实时反馈上传速度的小程序的bug
点击(此处)折叠或打开
-
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
-
// TODO Auto-generated method stub
-
int LENGTH=10240;
-
InputStream is=request.getInputStream();
-
String fn=UUID.randomUUID().toString();
-
File a=new File(HlsConfigure.getPath()+fn);
-
byte []content=new byte[LENGTH];
-
int length;
-
OutputStream os =new FileOutputStream(a);
-
PrintWriter out = response.getWriter();
-
out.write("<html><body><table><tr><td>bytes</td><td>speed KB/s</td></tr>");
-
long total=0;
-
long vb=System.currentTimeMillis();
-
again:
-
while(true){
-
int total_length=0;
-
long begin=System.currentTimeMillis();
-
while((length=is.read(content))!=-1){
-
os.write(content, 0, length);
-
System.out.println("get "+length);
-
total_length+=length;
-
if(total_length>=200*1024){
-
break;
-
}
-
}
-
System.out.println("will write speed");
-
long time=System.currentTimeMillis()-begin;
-
out.write("<tr><td>");
-
out.write(Integer.toString(total_length));
-
out.write("</td><td>");
-
out.write(Double.toString(total_length/(1.0240)/(time)));
-
out.write("</td></tr>");
-
total+=total_length;
-
out.flush();
-
if(length==-1)
-
break;
-
}
-
os.close();
-
long time=System.currentTimeMillis()-vb;
-
out.write("<tr><td>");
-
out.write(Long.toString(total));
-
out.write("</td><td>");
-
String speed=Double.toString(total/(1.0240)/(time));
-
out.write(speed);
-
out.write("</td></tr>");
-
out.flush();
-
out.write("</table></body></html>");
-
System.out.println("from "+request.getRemoteAddr()+ " speed is "+speed);
-
// a.delete();
- }
代码很简单:
1. 打开inputstream,读流,并写到文件中去;
2. 每200k反馈上传速度;
3. 客户段用最简单的input type=‘file‘上传文件;
但是当客户上传一个很大的文件时,不能传完就hang了。
最终分析到原因为:
1. 浏览器在没有完成发送请求时,是不会读取服务器输出的。所以这个实时显示上传速度的想法不对;
2. 从代码执行逻辑看,客户段上传,服务段收数据,不会导致服务器缓冲区满;
3. 但是由于1的原因,服务器返回给客户段的数据不会被从缓冲区读取。所以客户段的缓冲去会满;
4. 从而导致28行的write写不出去;
5. 由于此时服务器堵在了write处,所以服务器也不会再读取数据了。
6. 服务器的缓冲区满了,所以客户的上传就hang住了。
注意:
ACK报文是tcp协议栈实现的。所以无论程序是否读取缓冲区的数据,ACK是不会受到影响的。如果不都数据window值会变小; 这个标记可以用来指示程序是不是没有读数据;
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。