Skip to content

Latest commit

 

History

History
127 lines (93 loc) · 2.99 KB

《PHP扩展开发》-协程-server接收数据.md

File metadata and controls

127 lines (93 loc) · 2.99 KB

server接收数据

这一篇文章我们来实现一下服务器的recv。接口如下:

Study\Coroutine\Server->recv(int fd, int length = 65535): string | false;

首先,我们需要定义接口的参数,在文件study_server_coro.cc里面:

ZEND_BEGIN_ARG_INFO_EX(arginfo_study_coroutine_server_coro_recv, 0, 0, 2)
    ZEND_ARG_INFO(0, fd)
    ZEND_ARG_INFO(0, length)
ZEND_END_ARG_INFO()

然后实现recv接口:

PHP_METHOD(study_coroutine_server_coro, recv)
{
    int ret;
    zend_long fd;
    zend_long length = 65536;

    ZEND_PARSE_PARAMETERS_START(1, 2)
        Z_PARAM_LONG(fd)
        Z_PARAM_OPTIONAL
        Z_PARAM_LONG(length)
    ZEND_PARSE_PARAMETERS_END_EX(RETURN_FALSE);

    zend_string *buf = zend_string_alloc(length, 0);

    ret = stSocket_recv(fd, ZSTR_VAL(buf), length, 0);
    if (ret < 0)
    {
        php_error_docref(NULL, E_WARNING, "recv error");
        RETURN_FALSE;
    }
    ZSTR_VAL(buf)[ret] = '\0';
    RETURN_STR(buf);
}

首先,我们要明确一点,我们的length代表的是字符串的长度,不包括字符串结束符号\0。并且,zend_string是需要字符串结束符号。那么,为什么我们zend_string_alloc只传递了length而不是length + 1呢?因为zend_string_alloc底层帮我们做好了封装,我们只需要传递字符串的长度即可,zend_string_alloc里面会帮我们+1

stSocket_recv用来接收客户端发来的数据。我们先在include/socket.h里面声明这个函数:

ssize_t stSocket_recv(int sock, void *buf, size_t len, int flag)

然后在文件src/socket.cc里面进行实现:

ssize_t stSocket_recv(int sock, void *buf, size_t len, int flag)
{
    ssize_t ret;

    ret = recv(sock, buf, len, flag);
    if (ret < 0)
    {
        stWarn("Error has occurred: (errno %d) %s", errno, strerror(errno));
    }
    return ret;
}

最后,我们需要在zend_string的数据的后面加上\0

RETURN_STR(buf);设置返回值为我们接收到的数据。

然后我们注册这个方法:

static const zend_function_entry study_coroutine_server_coro_methods[] =
{
    // 省略其他注册的方法
    PHP_ME(study_coroutine_server_coro, recv, arginfo_study_coroutine_server_coro_recv, ZEND_ACC_PUBLIC)
    PHP_FE_END
};

现在重新编译、安装扩展:

~/codeDir/cppCode/study # make clean && make && make install

然后编写测试脚本:

<?php

$serv = new Study\Coroutine\Server("127.0.0.1", 8080);
$sock = $serv->accept();
$buf = $serv->recv($sock);
var_dump($buf);

执行脚本:

~/codeDir/cppCode/study # php test.php 

然后另开一个终端发送数据:

~/codeDir/cppCode/study # nc 127.0.0.1 8080
hello world

服务器这端将会打印出如下内容:

~/codeDir/cppCode/study # php test.php 
string(65536) "hello world
"

OK,符合预期。

下一篇:server发送数据