简体   繁体   English

ajax调用从php libevent客户端获取连续/流数据

[英]ajax call to get continuous/streaming data from php libevent client

I am looking for which ajax call or jquery api to be receiving streaming data from php libevent client. 我正在寻找哪个ajax调用或jquery api从php libevent客户端接收流数据。

The Libevent Client will be receiving data from Libevent Server.c Libevent客户端将从Libevent Server.c接收数据

Server.c 服务器

/* For socket functions */
#include <sys/socket.h>
#include <event2/event.h>
#include <event2/buffer.h>
#include <event2/bufferevent.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/un.h>
#include <event2/listener.h>

#include <arpa/inet.h>

#include <signal.h>

#define MAX_LINE 16384

void readcb(struct bufferevent *bev, void *ctx)
{
  /* This callback is invoked when there is data to read on bev. */
  struct evbuffer *input = bufferevent_get_input(bev);
  int len = evbuffer_get_length(input);
  char *data;
  data = malloc(len);
  evbuffer_copyout(input, data, len);
  free(data);
}

void writecb(struct bufferevent *bev, void *ctx)
{
  //here i will be checking my database and memcache new updates
  //it will wait randomly between 2 to 6 seconds to check again

  char *message = "Continuous message from your Server";
  evbuffer_add(bufferevent_get_output(bev), message, strlen(message));
  sleep(2+rand()%4);
}

void errorcb(struct bufferevent *bev, short error, void *ctx)
{
  if (error & BEV_EVENT_EOF) {
    /* connection has been closed, do any clean up here */
    /* ... */
  } else if (error & BEV_EVENT_ERROR) {
    /* check errno to see what error occurred */
    /* ... */
  } else if (error & BEV_EVENT_TIMEOUT) {
    /* must be a timeout event handle, handle it */
    /* ... */
  }
  bufferevent_free(bev);
}

void do_accept(evutil_socket_t listener, short event, void *arg)
{
  struct event_base *base = arg;
  struct sockaddr_storage ss;
  socklen_t slen = sizeof(ss);
  int fd = accept(listener, (struct sockaddr*)&ss, &slen);
  if (fd < 0) {
    perror("accept");
  } else if (fd > FD_SETSIZE) {
    close(fd);
  } else {
    struct bufferevent *bev;
    evutil_make_socket_nonblocking(fd);
    bev = bufferevent_socket_new(base, fd, BEV_OPT_CLOSE_ON_FREE);
    bufferevent_setcb(bev, readcb, writecb, errorcb, NULL);
    bufferevent_setwatermark(bev, EV_READ, 0, MAX_LINE);
    bufferevent_enable(bev, EV_READ|EV_WRITE);
  }
}

void run(void)
{
  evutil_socket_t listener;
  struct sockaddr_un sun;
  int len;
  struct event_base *base;
  struct event *listener_event;
  base = event_base_new();

  if (!base)
    return; /*XXXerr*/

  listener = socket(AF_UNIX, SOCK_STREAM, 0);
  evutil_make_socket_nonblocking(listener);

#ifndef WIN32
{
    int one = 1;
    setsockopt(listener, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
}
#endif

  memset(&sun, 0, sizeof(sun));

  sun.sun_family = AF_UNIX;
  strcpy(sun.sun_path, "/tmp/influenzaunix.sock");

  unlink(sun.sun_path);
  len = strlen(sun.sun_path) + sizeof(sun.sun_family);
  if (bind(listener, (struct sockaddr *)&sun, len) < 0) {
    perror("bind");
    return;
  }

  if (listen(listener, 16)<0) {
    perror("listen");
    return;
  }

  listener_event = event_new(base, listener, EV_READ|EV_PERSIST, do_accept, (void*)base);

  event_add(listener_event, NULL);

  event_base_dispatch(base);
}

int main(int c, char **v)
{
  setvbuf(stdout, NULL, _IONBF, 0);

  run();
  return 0;
}

Compiled with 编译与

gcc -o Server Server.c -levent

Then the Client.php is 然后Client.php是

<?php
define('MAX_LINE', '16384');
define('CHUNK_SIZE', '128');

class Server extends Thread{
    public function run(){
        passthru('./Server');
    }
}

class Client extends Thread{

    public function readcb($bev, $ctx)
    {
        $tmp = array();

        while (1) {
            $data = event_buffer_read($bev,CHUNK_SIZE);
            $size = strlen($data);
            if($size <= 0)
                break;
            $tmp[] = $data;
        }
        $data = implode($tmp);
        echo $data."\n"; //display the data received from server
        flush(); /*flush the data so that an ajax call will be receiving it*/
    }

    public function eventcb($bev, $events, $ptr)
    {
    }

    public function run()
    {
        $sockpath = '/tmp/influenzaunix.sock';
        $socket = stream_socket_client("unix://{$sockpath}",$errorNumber,$errorString,STREAM_CLIENT_CONNECT);
        stream_set_blocking($socket, 0); //non-blocking mode

        if (($socket) === FALSE){
            echo 'connect error';
        }
        else{
            $message = "Send data about this topic"; //subscribing to get data about a topic
            $bev = event_buffer_new($socket, array($this,"readcb"), NULL, array($this,"eventcb"));

            $base = event_base_new();

            if($base !== FALSE)
            {
                event_buffer_base_set($bev,$base);
                event_buffer_enable($bev, EV_READ|EV_WRITE);
                event_buffer_write($bev, $message, strlen($message));
            }

            event_base_loop($base);
        }
    }
}

$server = new Server();
$server->start();

sleep(3); /*let's wait for 3 seconds to make sure Server is ready to accept connection*/    

$client = new Client();
$client->start();
?>

The Client.php can only be run via CLI mode with RunClient.php below Client.php只能通过CLI模式与下面的RunClient.php一起运行

<?php
passthru('php Client.php');
?>

I am having a challenge to come up with an ajax call or jquery ajax call to be receiving the flushed data from Client.php. 我要提出一个ajax调用或jquery ajax调用来从Client.php接收刷新数据时遇到了挑战。 The JQuery ajax or Ajax call cannot call Client.php directly instead it will call RunClient.php. JQuery ajax或Ajax调用不能直接调用Client.php,而是将调用RunClient.php。 Please I will greatly appreciate if someone can make an attempt to provide an ajax call or Jquery ajax call to be receiving the flushed data. 如果有人可以尝试提供ajax调用或Jquery ajax调用来接收刷新的数据,我将不胜感激。

Testing with a browser is a first step to understand what is happening. 使用浏览器进行测试是了解正在发生的事情的第一步。

I am not familiar with php Thread class, but what may be happening is that when you call 我不熟悉php Thread类,但是可能发生的情况是当您调用

passthru('php Client.php');

in RunClient.php, the call is blocking, waiting for php Client.php to finish. 在RunClient.php中,调用被阻止,等待php Client.php完成。

Since Client.php is a long running server (it basically never ends), you never get an answer even tough you used flush() inside Client.php . 由于Client.php是一台运行时间很长的服务器(它基本上不会停止运行),因此即使您在Client.php使用flush()也很难得到答案。

You may want to try 您可能要尝试

<?php
$fp = fopen('php Client.php');
fpassthru($fp);
?>

to see if you see results in the browser (make sure your server emits data) 看看您是否在浏览器中看到结果(确保服务器发出数据)

After that, you mention that you want to use ajax. 之后,您提到要使用ajax。 You need to understand that an ajax call is a bit like a browser call : it is a request->response mechanism and not a streaming mechanism. 您需要了解ajax调用有点像浏览器调用:它是一种request-> response机制,而不是流机制。

you can try maybe with a script tag in your html page 您可以尝试在HTML页面中使用脚本标签

<script src='RunClient.php'/>

and modify your Client.php, instead of 并修改您的Client.php,而不是

echo $data."\n";

with

echo "document.write('<span>".$data."</span>');\n";

and simple datas without quotes. 和没有引号的简单数据。 If it works, you will need to escape the data so that the emitted string is valid javascript. 如果有效,则需要转义数据,以便发出的字符串是有效的javascript。

Of course, this is a prototype. 当然,这是一个原型。 It all depends on what you want to do. 这完全取决于您要做什么。

You may also want to use websockets for streaming. 您可能还需要使用websocket进行流式传输。 The protocol is made for streaming. 该协议用于流式传输。 cf https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API cf https://developer.mozilla.org/zh-CN/docs/Web/API/WebSockets_API

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM