模拟workerman的运行,在accept流程时卡住

dawn
<?php
$serv = stream_socket_server("tcp://0.0.0.0:2345", $errno, $errstr, STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);

stream_set_blocking($serv, 0);

for ($i = 0; $i < 3; $i++) {
    $pid = pcntl_fork();
    if ($pid === 0) {
        $base = event_base_new();
        $event = event_new();
        event_set($event, $serv, EV_READ | EV_PERSIST, 'accept_cb', $base);
        event_base_set($event, $base);
        event_add($event);
        event_base_loop($base);
        exit(0);
    }
}

function accept_cb($socket, $flag, $base)
{
    echo "onConnect\n";
    $conn = @stream_socket_accept($socket, 0);
    if(false === $conn)
    {
        return;
    }

    stream_set_blocking($conn, 0);

    $event = event_new();
    event_set($event, $conn, EV_READ | EV_PERSIST, 'read_cb', $base);
    event_base_set($event, $base);
    event_add($event);
}

function read_cb($conn, $flag, $base) {
    echo "onMessage\n";
    $data = fread($conn, 65535);
    $res = "hello: $data" . PHP_EOL;
    fwrite($conn, $res);
}

while(1) {
    $status = 0;
    $pid = pcntl_wait($status, WUNTRACED);
    if ($pid > 0) {
        echo "$pid onWorkerStop\n";
    }
}

在没有用event之前,我是用一个进程来维持一个长连接,每个进程中用一个变量来动态保存这个连接,这样连接就不会断掉。

上面这段代码用了event,可以执行到accept_cb,但是这个时候连接就会断掉。

看到workerman源码中,是把连接存到了一个_socket属性中,在read时,并没有用这个属性,是使用event传递的socket,一切正常。

大神请问,我这段代码怎么拯救呢,让它连接不断掉。

2323 1 0
1个回答

walkor

首先你要理解为什么会断掉。
因为accept_cb函数里面$conn是个临时变量,函数之行完$conn就销毁了,那么链接就断开了。

  • dawn 2016-06-07

    我把accept_cb函数里的$conn 都存到一个全局数组里,这样就不会断开连接了。但是客户端发送消息,服务端没有走read_cb函数。

  • walkor 2016-06-07

    你要会举一反三

  • dawn 2016-06-07

    恩 已经弄明白了。event也要存起来。非常感谢!

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