workerman源码读取socket数据

zhaocong

TcpConnection.php 文件中,baseRead方法中
读取socket代码如下:
$buffer = @fread($socket, self::READ_BUFFER_SIZE);

前后代码中并没有看到 while() 之类的验证数据读取完之类的代码。
假如把上述代码改为每次读取10个字节 $buffer = @fread($socket, 10);

请问是怎么样的机制保证每次从socket 读取完数据的?
然道这个和event loop 处理事件 中设置的 \Event::PERSIST参数有关吗?

\Event::PERSIST 的解释如下:
如果一个事件被设置了EV_PERSIST,那么这个事件就是持续化的,意思就是这个事件会保持挂起状态,即使回调函数被执行。

3344 7 0
7个回答

maq

是的,执行回调函数本身并没有清除这个事件,所以只要进入等待状态还会立刻触发。只有把数据读光了才会清除这个事件。

  • 暂无评论
damao

学习了

  • 暂无评论
zhaocong

1楼大神你好,我按照这个思路写了个简单的脚本,但是貌似有点问题,内层的读取数据event好像执行不了。问题出在哪?

  • maq 2018-04-20

    client 端发起连接时不能用 0.0.0.0 这个地址吧?……

  • zhaocong 2018-04-20

    可以额

  • maq 2018-04-20

    内层 new Event 的第二个参数对吗?

  • zhaocong 2018-04-20

    我改了下貌似还是不行

  • zhaocong 2018-04-20

    $event = new Event($event_base, $fd, Event::READ | Event::PERSIST, function ($fd) use (&$event_base) {

    //接收创建的socket
    $conn = stream_socket_accept($fd);
    stream_set_read_buffer($fd, 0);
    
    $event2 = new Event($event_base, $conn, Event::READ | Event::PERSIST, function ($conn) {
        $con = @fread($conn,2)."\n";
        echo $con."\n";
    },$conn);
    
    $event2->add();

    }, $fd);

zhaocong
$event = new Event($event_base, $fd, Event::READ | Event::PERSIST, function ($fd) use (&$event_base) {

    //接收创建的socket
    $conn = stream_socket_accept($fd);
    stream_set_read_buffer($fd, 0);
    $con = @fread($conn,2)."\n";
    echo $con;

}, $fd);

这么干是可以接收到的,但是读取数据就不基于事件循环了。

  • 暂无评论
walkor

$conn = stream_socket_accept($fd);
这个$conn是局部变量,出了函数作用域可能就销毁了,把它存在全局数组里试下

  • zhaocong 2018-04-23

    貌似不行额,问题是内层的event事件无法触发

zhaocong

内层的event事件(fread)无法触发

  • 暂无评论
zhaocong

此问题已解决,哈哈。
跟2个地方有关
1.event对象必须用个全局数组保存。
2.读取stream时需要把设置为无缓冲区。

  • 暂无评论
年代过于久远,无法发表回答
🔝