jquery — вызов ajax для получения непрерывных / потоковых данных от клиента php libevent

Я ищу, какой ajax-вызов или jquery api получать потоковые данные от клиента php libevent.

Клиент 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;
}

Составлено с

gcc -o Server Server.c -levent

Тогда 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();
?>

Client.php может быть запущен только через режим CLI с RunClient.php ниже

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

У меня есть проблема, чтобы придумать вызов ajax или вызов jjery ajax для получения сброшенных данных из Client.php. Вызов ajax или Ajax JQuery не может вызвать Client.php напрямую, вместо этого он вызовет RunClient.php. Пожалуйста, я буду очень признателен, если кто-то может предпринять попытку предоставить ajax-вызов или Jquery ajax-вызов для получения сброшенных данных.

0

Решение

Тестирование с помощью браузера — это первый шаг к пониманию происходящего.

Я не знаком с классом php Thread, но может случиться так, что при вызове

passthru('php Client.php');

в RunClient.php вызов блокируется, ожидая php Client.php заканчивать.

поскольку Client.php это долго работающий сервер (он в основном никогда не заканчивается), вы никогда не получите ответ, даже если вы использовали flush() внутри Client.php,

Вы можете попробовать

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

чтобы увидеть, если вы видите результаты в браузере (убедитесь, что ваш сервер выдает данные)

После этого вы упоминаете, что хотите использовать ajax. Вы должны понимать, что ajax-вызов немного похож на вызов браузера: это механизм запроса-> ответа, а не механизм потоковой передачи.

Вы можете попробовать, возможно, с тегом сценария на вашей HTML-странице

<script src='RunClient.php'/>

и измените ваш Client.php вместо

echo $data."\n";

с

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

и простые данные без кавычек. Если это работает, вам нужно будет экранировать данные, чтобы выдаваемая строка была действительным javascript.

Конечно, это прототип. Все зависит от того, что вы хотите сделать.

Вы также можете использовать веб-сокеты для потоковой передачи. Протокол сделан для потоковой передачи. сравни https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]