|
php.net | support | documentation | report a bug | advanced search | search howto | statistics | random bug | login |
[2012-07-14 17:08 UTC] omarvillanueva at gmail dot com
Description:
------------
I am trying to use a connection opened with stream_socket_client() on PHP, and
handle the response from the remote server through a READ event with libevent.
Sadly, there are no examples of this in the PHP documentation. The usual approach
using while (!feof($fp)) { //something } or any other blocking approach is not
good enough for me, because I'm writing something like a relay server, hence the
need of libevent.
As you can see in the code snippet, it looks perfectly normal, but the
onReceive() callback never gets called. If I change it for EV_WRITE|EV_PERSIST
(or if I create an event for writes), it gets called, but obviously no data is
received.
BTW, the snippet works great if I use stream_socket_server, but that's not what I
want to do.
Test script:
---------------
$fp = stream_socket_client("tcp://some_host:some_port", $errno, $errstr);
stream_set_blocking($fp, 0);
$base = event_base_new();
$event_fd = event_new();
event_set($event_fd, $fp, EV_READ| EV_PERSIST, 'onReceive');
event_base_set($event_fd, $base);
event_add($event_fd);
event_base_loop($base);
Expected result:
----------------
I expect that the "onReceive" callback function gets called on every incoming
data on a stream_socket_client connection.
Actual result:
--------------
The "onReceive" never gets called.
PatchesPull RequestsHistoryAllCommentsChangesGit/SVN commits
|
|||||||||||||||||||||||||||
Copyright © 2001-2025 The PHP GroupAll rights reserved. |
Last updated: Sat Nov 08 05:00:02 2025 UTC |
UPDATE: The provided snippet wasn't accurate enough, and actually there was no bug in it. What I tried to do was starting an event loop inside another triggered event, which failed. I managed to make it work by creating the new event inside a new fork with pcntl_fork(). I've read the libevent documentation and it says that a new base should be used, but when I call event_base_loop(), it blocks the previous one, and no new events are triggered in it until the new one ends. I'd like to know if there's any way to do it without pcntl_fork(). Am I missing something? I've created a proof of concept here: <?php class Relay{ private $connectionHandler; private $newHandler; public function test(){ $this->connectionHandler = stream_socket_client("tcp://localhost:80", $errno, $errstr); if (!$this->connectionHandler) { echo "CRITICAL ERROR: $errstr ($errno)\n"; exit; } stream_set_blocking($this->connectionHandler, 0); $this->eventBase = event_base_new(); $buf = event_buffer_new($this->connectionHandler, array($this, 'onReceive'), array($this, 'onWrite'), array($this, 'onError'), $this- >eventBase); event_buffer_base_set($buf, $this->eventBase); event_buffer_priority_set($buf, 10); event_buffer_watermark_set($buf, EV_READ, 0, 0xFFFFFF); event_buffer_enable($buf, EV_READ | EV_PERSIST); event_base_loop($this->eventBase); } public function onReceive($buffer, $base) { $receiveBuffer = null; while ($rawData = event_buffer_read($buffer, 256)) { echo "RECEIVED DATA AT 1: ".$rawData; $receiveBuffer .= $rawData; } if (!$this->newHandler){ echo "CREATING NEW CONNECTION...\n"; $this->newHandler = stream_socket_client("tcp://localhost:999", $errno, $errstr); if (!$this->newHandler) { echo "CRITICAL ERROR: $errstr ($errno)\n"; exit; } stream_set_blocking($this->newHandler, 0); if (-1 == ($pid = pcntl_fork())){ echo "COULD NOT FORK"; exit; }else if ($pid == 0){ $this->createNewConnection($this->newHandler); exit; }else{ //parent process //do something } } fwrite($this->newHandler, $receiveBuffer); } public function onWrite($buffer, $args) { echo "WRITE AT 1\n"; } public function onError($buffer, $base) { echo "ERROR AT 1\n"; } public function onReceive2($buffer, $args){ $receiveBuffer = null; while ($rawData = event_buffer_read($buffer, 256)) { echo "RECEIVED DATA AT 2: ".$rawData; $receiveBuffer .= $rawData; } fwrite($this->connectionHandler, $receiveBuffer); } public function onWrite2($buffer, $args) { echo "WRITE AT 2\n"; } public function onError2($buffer, $args) { echo "ERROR AT 2\n"; } private function createNewConnection($newHandler){ $newBase = event_base_new(); $buf = event_buffer_new($newHandler, array($this, 'onReceive2'), array($this, 'onWrite2'), array($this, 'onError2'), $newBase); event_buffer_base_set($buf, $newBase); event_buffer_priority_set($buf, 9); event_buffer_watermark_set($buf, EV_READ, 0, 0xFFFFFF); event_buffer_enable($buf, EV_READ | EV_PERSIST); event_base_loop($newBase); } } $relayTest = new Relay(); $relayTest->test();