2 j2merr j2merr 于 2014.12.04 09:46 提问

请问大家,浏览器关闭动态网页,服务器端能侦听到 吗 ?

场景一:浏览器关闭网页,服务器端能知道 吗?
场景二:android客户端下载页面或文件,然后取消下载,服务器端能知道 吗 ?

    我用java代码中的 HttpClient  和 HttpURLConnection 模拟测试,关闭连接 

httpclient.getConnectionManager().shutdown(); 和 httpUrlConnection.disconnect(); 后 服务器端都是不知道的
请问大家, 是确实服务器端侦测不到,还是我方法不对?

5个回答

save4me
save4me   Ds   Rxr 2014.12.04 10:04

参考HTTP无状态协议

HTTP协议是无状态协议。
无状态是指协议对于事务处理没有记忆能力。缺少状态意味着如果后续处理需要前面的信息,则它必须重传,这样可能导致每次连接传送的数据量增大。另一方面,在服务器不需要先前信息时它的应答就较快。

参考http协议和web应用有状态和无状态辨析

http协议作为技术背景的web应用程序请求——应答模式是无状态的,这个事实基本不会发生改变,也不会因为加入cookies、session机制而变成有状态的。要明白,这种前后因果关系:“我们要实现的是一种web应用,实现这种应用的协议我们选择了http这种本质上是无状态的通信协议。但是事实上,我们需要我们的web应用是有状态的。所以我们加入了cookies、session等机制去实现由状态的web应用”。所以我们可以这么理解:
Web应用=http协议+session、cookies等状态机制+其他辅助的机制。

如果想知道客户端是否关闭,需要客户端想服务器端报告,比如通过jsJS监听关闭浏览器事件之Onunload与Onbeforeunload,当然,可能还有其他方法

j2merr
j2merr 谢谢,我是想,如何不需要报告的情况下,让服务器端知道,如果通知的话,需要改动android客户端的代码,
接近 3 年之前 回复
tangbo713
tangbo713   2014.12.04 09:57

场景一:浏览器关闭网页,服务器端能知道 吗?
服务器不知道
场景二:android客户端下载页面或文件,然后取消下载,服务器端能知道 吗 ?
这就看你下载文件采用什么方式,如果你在下载的时候服务器监听下载流的话,服务器可以知道是否取消下载。否则不知道!

j2merr
j2merr 因为http是无状态的,所以场景一无异议
接近 3 年之前 回复
xuzuning
xuzuning   Ds   Rxr 2014.12.04 09:58

如果当前会话尚未结束,是可以侦听到的
否则不可以

j2merr
j2merr 回复j2merr: 但是楼上说,http是无状态的,有点懵
接近 3 年之前 回复
j2merr
j2merr 这么说正在下载的过程中,服务器是能知道的,是吗,如何知道?
接近 3 年之前 回复
o0lcl0o
o0lcl0o   2014.12.04 10:01

你需要的是长连接,普通的http请求服务器响应后就断开了,关闭浏览器服务端不可能知道的,看看tomcat的comet

j2merr
j2merr 普通的http请求服务器响应后就断开了,这怎么理解,不是一次会话结束后才断开吗?可在文件下载的时候,文件没下载完,会话还没结束。你的意思是,会话结束前,http请求就断开了?
接近 3 年之前 回复
j2merr
j2merr   2014.12.04 11:33

对于场景二:
String fileName = fileInfo.getOriginalName();
String nowPath = PropertyUtil.get("root_dir") + fileInfo.getFilePath();
response.setContentType("application/x-download");

    InputStream in = null;
    OutputStream out = null;

    try {
        // 以流的形式下载文件
        in = new BufferedInputStream(new FileInputStream(nowPath));
        out = new BufferedOutputStream(response.getOutputStream());
        byte[] b = new byte[1024];
        int i = 0;
        while ((i = in.read(b)) > 0) {
            out.write(b, 0, i);
        }
        out.flush();
        // out.close();
        fileDevice.setFileStatus(FileConstant.FILE_STATUS_DOWNLOAD);
        this.fileDeviceRelationService.updateFileDeviceRelationByCondition(fileDevice);
    } catch (Exception e) {
        logger.debug("/content/download_contents error by " + e.getMessage(), e.getCause());
        httpStatus = org.springframework.http.HttpStatus.NOT_FOUND;
        return new ResponseEntity<Map<String, Object>>(map, httpStatus);
    } finally {
        if (in != null) {
            in.close();
            in = null;
        }
        if (out != null) {
            out.close();
            out = null;
        }
    }
    return new ResponseEntity(httpStatus);



            以上是程序代码,设计的初衷是:
                   Android客户端在下载文件的时候,如有没有此文件,就告诉客户端,此文件未找到,如果有此文件,就将文件流response给android客户端。
                    Android客户端正在下载文件的时候,如果客户端取消下载(会调用httpclient.getConnectionManager().shutdown();),那么服务器端能catch到 连接被中断的 IO异常,可实际情况是,服务器根本不知道连接被中断,因此无法知道 客户端取消下载了。
                    我的理解是,这种文件下载,通过流传输,也是建立一种tcp连接,按道理,在传输的过程中,一端关闭,另一端是知道的。
                    到底是我理解的有问题,还是 程序写的有问题呢?
Csdn user default icon
上传中...
上传图片
插入图片