PHP中的socket_read和socket_recv区别详解


Posted in PHP onFebruary 09, 2015

前几天用PHP写一个socket网络服务,在文档里看到socket_read和socket_recv这两个方法时有点晕,乍一看这不是一样的嘛,干吗还要给两个不同的用法呢。看文档没看太明白,看了下源码才搞清楚,在这里记录一下。

先看一下这两个函数的声明:

string socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] )

int socket_recv ( resource $socket , string &$buf , int $len , int $flags )

可以看到,从声明可以看到,一个是把收到的数据通过执行结果返回,另一个是把收到的数据通过引用的形式返回。另一个区别就是,socket_read多了一个type,socket_recv多了一个flags(够混乱的)。我们先来看看socket_recv的源码吧!
PHP_FUNCTION(socket_recv)

{

    zval        *php_sock_res, *buf;

    char        *recv_buf;

    php_socket  *php_sock;

    int         retval;

    long        len, flags;
    if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rzll", &php_sock_res, &buf, &len, &flags) == FAILURE) {

        return;

    }
    ZEND_FETCH_RESOURCE(php_sock, php_socket *, &php_sock_res, -1, le_socket_name, le_socket);
    /* overflow check */

    if ((len + 1) < 2) {

        RETURN_FALSE;

    }
    recv_buf = emalloc(len + 1);

    memset(recv_buf, 0, len + 1);
    if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {

        efree(recv_buf);
        zval_dtor(buf);

        Z_TYPE_P(buf) = IS_NULL;

    } else {

        recv_buf[retval] = '\0';
        /* Rebuild buffer zval */

        zval_dtor(buf);
        Z_STRVAL_P(buf) = recv_buf;

        Z_STRLEN_P(buf) = retval;

        Z_TYPE_P(buf) = IS_STRING;

    }
    if (retval == -1) {

        PHP_SOCKET_ERROR(php_sock, "unable to read from socket", errno);

        RETURN_FALSE;

    }
    RETURN_LONG(retval);

}

????乱淮蠖眩?涫涤幸恍凶罟丶??br />

if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {

可以看到,实际上这个函数就是调用了系统的recv而已,只是把输入参数和得到的结果都处理了一下,比较好理解。那我们再来看下socket_read,socket_read比系统的recv函数多了一个$type参数,这也是我认为这个函数存在的意义,从文档里可以看到,type有两个值,分别是PHP_BINARY_READ和PHP_NORMAL_READ,文档里有写,PHP_BINARY_READ表示直接用系统的recv方法,PHP_NORMAL_READ表示会一读,直到遇到\n 或者 \r,我们来看下源码:
//省略一大堆

if (type == PHP_NORMAL_READ) {

    retval = php_read(php_sock, tmpbuf, length, 0);

} else {

    retval = recv(php_sock->bsd_socket, tmpbuf, length, 0);

}

可以看到,如果是PHP_NORMAL_READ模式,其实行为和socket_recv是一样的,都是用的系统的recv函数,但是如果是PHP_NORMAL_READ,则有很大区别,用了自己实现的php_read函数,那这个php_read是干啥的呢?我们继续看源码:
*t = '\0';

while (*t != '\n' && *t != '\r' && n < maxlen) {

    if (m > 0) {

        t++;

        n++;

    } else if (m == 0) {

        no_read++;

        if (nonblock && no_read >= 2) {

            return n;

            /* The first pass, m always is 0, so no_read becomes 1

             * in the first pass. no_read becomes 2 in the second pass,

             * and if this is nonblocking, we should return.. */

        }
        if (no_read > 200) {

            set_errno(ECONNRESET);

            return -1;

        }

    }
    if (n < maxlen) {

        m = recv(sock->bsd_socket, (void *) t, 1, flags);

    }
    if (errno != 0 && errno != ESPIPE && errno != EAGAIN) {

        return -1;

    }
    set_errno(0);

}

还是指copy了关键部分,可以看到,这里的实现是一直循环调用recv,直到遇到\r或者\n或者读的数据长度到了指定的maxlen。

虽然这两个函数比较混乱,但是看到这里应该明白了吧!好了睡觉去啦!

PHP 相关文章推荐
在IIS上安装PHP4.0正式版
Oct 09 PHP
PHP实现定时生成HTML网站首页实例代码
Nov 20 PHP
php中使用Imagick实现图像直方图的实现代码
Aug 30 PHP
php 搜索框提示(自动完成)实例代码
Feb 05 PHP
如何用php获取文件名后缀
Jun 09 PHP
常见php数据文件缓存类汇总
Dec 05 PHP
php实现在多维数组中查找特定value的方法
Jul 29 PHP
golang与PHP输出excel示例
Jul 22 PHP
PHP htmlspecialchars() 函数实例代码及用法大全
Sep 18 PHP
PHP实现的权重算法示例【可用于游戏根据权限来随机物品】
Feb 15 PHP
php和html的区别点详细总结
Sep 24 PHP
详解PHP用mb_string处理windows中文字符
May 26 PHP
支持png透明图片的php生成缩略图类分享
Feb 08 #PHP
基于GD2图形库的PHP生成图片缩略图类代码分享
Feb 08 #PHP
php中get_object_vars()方法用法实例
Feb 08 #PHP
php面向对象中static静态属性与方法的内存位置分析
Feb 08 #PHP
php面向对象中static静态属性和静态方法的调用
Feb 08 #PHP
php延迟静态绑定实例分析
Feb 08 #PHP
PHP调用Linux命令权限不足问题解决方法
Feb 07 #PHP
You might like
PHP __autoload函数(自动载入类文件)的使用方法
2012/02/04 PHP
全新的PDO数据库操作类php版(仅适用Mysql)
2012/07/22 PHP
真正根据utf8编码的规律来进行截取字符串的函数(utf8版sub_str )
2012/10/24 PHP
php防注入,表单提交值转义的实现详解
2013/06/10 PHP
destoon实现调用当前栏目分类及子分类和三级分类的方法
2014/08/21 PHP
基于ThinkPHP删除目录及目录文件函数
2020/10/28 PHP
jQuery 回车事件enter使用示例
2014/02/18 Javascript
Node调试工具JSHint的安装及配置教程
2014/05/27 Javascript
Javascript无参数和有参数类继承问题解决方法
2015/03/02 Javascript
jQuery实现图片预加载效果
2015/11/27 Javascript
requirejs按需加载angularjs文件实例
2017/06/08 Javascript
JavaScript上传文件时不用刷新页面方法总结(推荐)
2017/08/15 Javascript
JS实现图片切换特效
2019/12/23 Javascript
解决echarts vue数据更新,视图不更新问题(echarts嵌在vue弹框中)
2020/07/20 Javascript
用smtplib和email封装python发送邮件模块类分享
2014/02/17 Python
Python网络爬虫与信息提取(实例讲解)
2017/08/29 Python
python reduce 函数使用详解
2017/12/05 Python
Python实现可设置持续运行时间、线程数及时间间隔的多线程异步post请求功能
2018/01/11 Python
浅述python2与python3的简单区别
2018/09/19 Python
Django使用unittest模块进行单元测试过程解析
2019/08/02 Python
Python编译成.so文件进行加密后调用的实现
2019/12/23 Python
Python装饰器原理与基本用法分析
2020/01/07 Python
css3学习之2D转换功能详解
2016/12/23 HTML / CSS
纯CSS3实现圆圈动态发光特效动画的示例代码
2021/03/08 HTML / CSS
英国在线电子和小工具商店:TecoBuy
2018/10/06 全球购物
美国领先的宠物用品和宠物食品零售商:Petco
2020/10/28 全球购物
工程地质勘察专业大学生求职信
2013/10/13 职场文书
餐厅楼面主管岗位职责范本
2014/02/16 职场文书
行政部岗位职责范本
2014/03/13 职场文书
三八妇女节超市活动方案
2014/08/18 职场文书
四风查摆剖析材料
2014/10/10 职场文书
2015年元旦晚会活动总结(学生会)
2014/11/28 职场文书
汽车销售员岗位职责
2015/04/11 职场文书
监守自盗观后感
2015/06/10 职场文书
教师工作证明范本
2015/06/12 职场文书
只需要这一行代码就能让python计算速度提高十倍
2021/05/24 Python