洛必达法则 发表于 2017-7-1 15:49:09

请教一个关于iframe实现反向Ajax的问题

这个问题源于一个贴子<<使用反向Ajax技术做在线客服系统>>,地址如下
使用反向Ajax技术做在线客服系统
http://blog.csdn.net/baochao95/article/details/52822098
原PHP的方式已经实现,确实可用。之后就想着用CI改写一下。碰到如下问题。
控制器中kefu_iframe部分,无论如何调整都无法实现iframe长连接功能,只能加了exit('55555')后,会实现客服和系统对话功能,但只能执行一次。查了挺多资料,都没有办法实现来回对话的交互功能。
分析了几点:
①CI的VIEW缓存问题,感觉是控制器中的内容如果不执行完,VIEW部分是无法加载的。
②sleep在中间似乎不起作用。



控制器文件 Ajaxke.php

<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Ajaxke extends Controller {

    /**
   * Index Page for this controller.
   *
   * Maps to the following URL
   *      http://example.com/index.php/welcome
   *- or -
   *      http://example.com/index.php/welcome/index
   *- or -
   * Since this controller is set as the default controller in
   * config/routes.php, it's displayed at http://example.com/
   *
   * So any other public methods not prefixed with an underscore will
   * map to /index.php/welcome/<method_name>
   * @see https://codeigniter.com/user_guide/general/urls.html
   */

    public function __construct(){
      parent::__construct();
      // $this->db->close();
      $this->load->model('m_ajax');

    }
    public function index()
    {

      $this->load->view('ajaxkefu_admin', TRUE);

    }

    public function kefu_iframe(){
      //<meta http-equiv="Content-Type" content="text/html"; charset=utf-8">
      //$this->output->set_content_type('text/plain', 'UTF-8');
      // $this->output->set_content_type('text/html', 'UTF-8');
      // echo $this->output->get_header('content-type');
      echo '************';
      // echo $this->output->get_header('content-type');
      // exit();
      header('Content-type:text/html; charset=utf-8');
      set_time_limit(0);
      // ob_start();
      ob_end_clean();
      echo str_pad(' ', 4096);
      // ob_flush();
      // flush();


      while (true) {
            $sql = "select * from msg where rec = 'admin' and isread = 0 limit 0,1";
            $msg = $this->m_ajax->getOnemsg($sql)->row_array();
            // echo $msg; echo '<br />';
            if (!empty($msg)) {
                ob_end_clean();
                $sql = 'update msg set isread = 1 where mid = '.$msg['mid'];
                // echo $sql; exit('333333333');
                // parent.window.comet({"mid":"28","rec":"admin","pos":"asdf","isread":"0","content":"asdfasdf"})
                $this->m_ajax->getOnemsg($sql);
                $json = json_encode($msg);
                // sleep(5);
                echo "<script>parent.window.comet($json); </script>";
                // sleep(5);
                $this->output->_display();
                exit('55555555555555');
                ob_flush();
                flush();
                sleep(1);
            }

            sleep(1);         
      }

    }


    public function kefu_ajax(){
      set_time_limit(0);
      $rec = $_COOKIE['username'];
      $sql = "select * from msg where rec = '$rec' and isread =0 limit 0,1";
      // exit($rec);
      while (true) {
            $msg = $this->m_ajax->getOnemsg($sql)->row_array();

            if (!empty($msg)) {
                $sql = "update msg set isread = 1 where mid = ".$msg['mid'];
                $this->m_ajax->getOnemsg($sql);
                echo json_encode($msg);
                exit();
            }
            sleep(1);
      }
    }

    public function kefu_sendmsg(){
      header('Content-type:text/html;charset=utf-8');
      // $db = $this->load->database('ajax',true);
      $rec = $_POST['rec'];
      $pos = $_COOKIE['username'];
      $respContent = $_POST['content'];

      // $rec = 'admin';
      // $pos = 'still';
      // $respContent = 'come on ';
      $sql = "insert into msg (pos,rec,content) values ('$pos', '$rec', '$respContent')";
      $res = $this->m_ajax->insertOnemsg($sql);
      echo $res?'ok':'fail';   
    }


    public function keuser()
    {

      setcookie('username', 'user'.rand(10000,99999));
      $this->load->view('kefu_user');

    }

}





视图文件:ajaxkefu_admin.php

<?php
    setcookie('username','admin')
?>
<html>
<!DOCTYPE html>
<!-->      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <!-->
<!-->         <html class="no-js lt-ie9 lt-ie8"> <!-->
<!-->         <html class="no-js lt-ie9"> <!-->
<!--><!--> <html class="no-js"> <!--<!-->
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
    <title>Closest — 100% Free Fully Responsive HTML5 Template by FREEHTML5.co</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <meta name="description" content="Free HTML5 Template by FREEHTML5" />
    <meta name="keywords" content="free html5, free template, free bootstrap, html5, css3, mobile first, responsive" />

    <!--ajaxke.css -->
    <link rel="stylesheet" href="<?php echo _CSSPATH_ ; ?>style.css">
    <script src="<?php echo _JSPATH_ ; ?>kefuadmin.js"></script>


    <!-- Facebook and Twitter integration -->
    <meta property="og:title" content=""/>
    <meta property="og:image" content=""/>
    <meta property="og:url" content=""/>
    <meta property="og:site_name" content=""/>
    <meta property="og:description" content=""/>
    <meta name="twitter:title" content="" />
    <meta name="twitter:image" content="" />
    <meta name="twitter:url" content="" />
    <meta name="twitter:card" content="" />

    <!-- Place favicon.ico and apple-touch-icon.png in the root directory -->
    <link rel="shortcut icon" href="favicon.ico">

    <linkrel='stylesheet' type='text/css'>


    </head>
<body>

    <h1>客服功能--客服人员端</h1>
    <h2>原理:iframe+长连接</h2>

    <div id="chatArea">   
    </div>
      <hr>   
      <iframe name="frame" frameborder="0" src="<?php echo __ADMIN__DO_MAIN; ?>/ajaxke/kefu_iframe"></iframe>
      <p>咨询人:<span id="postman"></span></p>
      <p><textarea id="respContent"></textarea></p>
      <p><input type="button" value="回复" /></p>

</body>
</html>



Hex 发表于 2017-7-2 16:49:46

你说对了,确实是控制器不执行完不会输出视图,因为用了 output buffer,你可以强制 flush,或者修改下 CI 源码

洛必达法则 发表于 2017-7-2 18:03:29

Hex 发表于 2017-7-2 16:49
你说对了,确实是控制器不执行完不会输出视图,因为用了 output buffer,你可以强制 flush,或者修改下 CI...

感谢,您说的强制flush,是指在循环中使用ob_flush()和flush()么?这个已经用了,但似乎并不起什么作用。现在在修改CI源码解决这个问题。
解决这个问题的时候,闪出这样一个想法。其实像Iframe长连接的这种技术并不适合http这种无状态,或者理解为当年Ajax的一种变通。
感谢您!

Hex 发表于 2017-7-3 10:23:25

洛必达法则 发表于 2017-7-2 18:03
感谢,您说的强制flush,是指在循环中使用ob_flush()和flush()么?这个已经用了,但似乎并不起什么作用。 ...

你可以看看 http://codeigniter.org.cn/user_guide/libraries/output.html 里的 _display 方法。

洛必达法则 发表于 2017-7-7 16:33:39

尝试了两种方法,一种在_display中修改,另外一种在loader下的view中修改。_display修改有些效果,但是真正交互没有完全实现,基本就是对话两次到三次。
之后,讨巧在resp()下加了自刷新,基本实现多次对话,但由于刷新了页面,相当于cookie也修改了,不太完美。
所以修改__display()路数还是比较靠谱的。
由于最近工作比较紧张,加上初识CI,暂时研究自此,算在TODO LIST下。等有空闲时间好好研究一下CI。
非常感谢@Hex 指点!!!
页: [1]
查看完整版本: 请教一个关于iframe实现反向Ajax的问题