发现客户端关闭浏览器,服务端无法关闭链接

ztj7157

以下程序使用的是 windows 版,我正在测试 linux 版。

今天写了一个程序,程序要求客户端执行服务端的shell,有的是常规的shell,有的是shell监听的任务。

我把两个任务作为如下示例:
ping www.baidu.com
ping www.sina.com -t

baidu作为一个短期的shell命令,sina作为一个长期监视的shell命令。

在执行中发现:
1.如果浏览器执行 sina 中,浏览器关闭了,那么服务端仍然在执行,不会关闭当前任务;

如果 baidu 未执行完毕时,执行了 sina,那么浏览器会在 baidu 执行完毕时执行 sina
如果先执行 sina,然后再执行 baidu,那么返回的消息一直属于 sina,baidu 没有返回

$worker->onMessage = function ($connection, $data) {
    if (($connection->handle = popen($data, 'r'))) {
        $connection->send('----- Task Start -----');
        while (!feof($connection->handle)) {
            $str = fread($connection->handle, 1024);
            echo $str, "\n";
            $connection->send($str);
        }
        $connection->send('----- Task End -----');
        $connection->close();
    }
};

$worker->onClose = function ($connection) {
    fclose($connection->handle);
};

前端代码:

<script>
    function execWebSocket(task){
        var ws = new WebSocket("ws://127.0.0.1:2345");
        ws.onopen = function() {
            console.log("----- WebSocket Start -----");
            ws.send(task);
        };
        ws.onmessage = function(msg) {
            console.log(msg.data);
        };
        ws.onclose = function() {
            console.log("----- WebSocket End -----");
        };
        return ws;
    }
    //execWebSocket("ping www.baidu.com");
    //execWebSocket("ping www.sina.com -t");
</script>

这里的前端我采用执行一个shell,打开关闭一次链接的模式,这是使用所有的命令始终使用一个 WebSocket 对象好,还是像我这样,一个shell创建一次WebSocket好。

希望大神指点一下方向。

4029 6 0
6个回答

ztj7157

经过测试 linux 可以支持多个任务并行执行。

但是仍然存在客户端关闭,服务端仍在执行的情况。

  • 暂无评论
walkor

执行ping sina时,while (!feof($connection->handle))一直成立的,所以程序一直在while里死循环,导致workerman无法得到程序控制权,即使客户端断开链接,workerman无法运行到onClose。

  • ztj7157 2016-12-24

    假如我一台服务器开了 10 个进程,有20个客户,每个客户执行一个 sina (监视任务),那么是不是我只有10个客户能执行成功 sina (监视任务),其他的客户都会在等待状态,同时所有客户的baidu (短耗时)任务也没法执行

ztj7157

假如我一台服务器开了 10 个进程,有20个客户,每个客户执行一个 sina (监视任务),那么是不是我只有10个客户能执行成功 sina (监视任务),其他的客户都会在等待状态,同时所有客户的baidu (短耗时)任务也没法执行

  • 暂无评论
ztj7157

我的这个需求是需要监视一个目录的文件变化然后复制到其他目录中去,同时还有一个直接复制的命令 (类似于这样),请问有什么建议吗?假如有20个客户监视20个目录的情况下 (当然不是php监视,而是一个其他 shell 程序)。

  • 暂无评论
ztj7157

经过测试,客户的每个短耗时执行时常(shell)需要5秒,长监视任务(shell)为一直执行,不过只有文件改变触发才会返回数据,有一台 32 线程,64G内存的服务器 (局域网),如果公司 100 个员工的话,这台服务器是否可以支撑,同时对代码上您有什么优化建议吗?

  • 暂无评论
walkor

你可以看下这个demo
http://www.workerman.net/workerman-vmstat
关键代码如下

// 进程启动时,开启一个vmstat进程,并广播vmstat进程的输出给所有浏览器客户端
$worker->onWorkerStart = function($worker)
{
    // 把进程句柄存储起来,在进程关闭的时候关闭句柄
    $worker->process_handle = popen('vmstat 1', 'r');
    if($worker->process_handle)
    {
        $process_connection = new TcpConnection($worker->process_handle);
        $process_connection->onMessage = function($process_connection, $data)use($worker)
        {
            foreach($worker->connections as $connection)
            {
                $connection->send($data);
            }
        };
    }
    else
    {
        echo "vmstat 1 fail\n";
    }
};

另外php也可以用inotify扩展监听操作系统磁盘目录文件访问修改
参考 https://github.com/walkor/workerman-filemonitor-inotify

以上都是利用异步IO做的,支撑几万客户端都没事

  • ztj7157 2016-12-24

    文件的修改只是举个例子,监视任务是由外壳程序(shell)决定的 (改动后的处理也是由外壳程序自动处理的,否则又数据一致性的问题),公司的需求也是奇葩;我看得的改改需求;如果 100 个目录 (员工),每个员工 1K 个文件;员工上班时基本上文件都在改动状态,这个需求也有点大;看来必要把监视任务去掉,只执行那个手动耗时 5s 的任务了

  • ztj7157 2016-12-24

    谢谢您了,祝您圣诞节快乐!

  • walkor 2016-12-24

    不客气

年代过于久远,无法发表回答
🔝