Maison php教程 php手册 PHP中的socket_read和socket_recv区别详解

PHP中的socket_read和socket_recv区别详解

Jun 06, 2016 pm 08:10 PM
php 区别

这篇文章主要介绍了PHP中的socket_read和socket_recv区别详解,本文从源码上分析了这两个函数的不同之处,需要的朋友可以参考下

前几天用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)         RETURN_FALSE;
    }

    recv_buf = emalloc(len + 1);
    memset(recv_buf, 0, len + 1);

    if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags))         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);
}

啰里啰嗦一大堆,其实有一行最关键:

复制代码 代码如下:


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


可以看到,实际上这个函数就是调用了系统的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     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         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。

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

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn

Article chaud

Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Article chaud

Repo: Comment relancer ses coéquipiers
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Combien de temps faut-il pour battre Split Fiction?
3 Il y a quelques semaines By DDD
R.E.P.O. Crystals d'énergie expliqués et ce qu'ils font (cristal jaune)
1 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island Adventure: Comment obtenir des graines géantes
3 Il y a quelques semaines By 尊渡假赌尊渡假赌尊渡假赌

Tags d'article chaud

Bloc-notes++7.3.1

Bloc-notes++7.3.1

Éditeur de code facile à utiliser et gratuit

SublimeText3 version chinoise

SublimeText3 version chinoise

Version chinoise, très simple à utiliser

Envoyer Studio 13.0.1

Envoyer Studio 13.0.1

Puissant environnement de développement intégré PHP

Dreamweaver CS6

Dreamweaver CS6

Outils de développement Web visuel

SublimeText3 version Mac

SublimeText3 version Mac

Logiciel d'édition de code au niveau de Dieu (SublimeText3)

Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian Dec 24, 2024 pm 04:42 PM

Guide d'installation et de mise à niveau de PHP 8.4 pour Ubuntu et Debian

Bitcoin a-t-il des actions? Bitcoin a-t-il des actions? Mar 03, 2025 pm 06:42 PM

Bitcoin a-t-il des actions?

Comment configurer Visual Studio Code (VS Code) pour le développement PHP Comment configurer Visual Studio Code (VS Code) pour le développement PHP Dec 20, 2024 am 11:31 AM

Comment configurer Visual Studio Code (VS Code) pour le développement PHP

Deepseek Quelle est la différence entre la version R1 et V3 Deepseek Quelle est la différence entre la version R1 et V3 Feb 19, 2025 pm 03:24 PM

Deepseek Quelle est la différence entre la version R1 et V3

Résumé des FAQ pour une utilisation profonde Résumé des FAQ pour une utilisation profonde Feb 19, 2025 pm 03:45 PM

Résumé des FAQ pour une utilisation profonde

Comment analysez-vous et traitez-vous HTML / XML dans PHP? Comment analysez-vous et traitez-vous HTML / XML dans PHP? Feb 07, 2025 am 11:57 AM

Comment analysez-vous et traitez-vous HTML / XML dans PHP?

Programme PHP pour compter les voyelles dans une chaîne Programme PHP pour compter les voyelles dans une chaîne Feb 07, 2025 pm 12:12 PM

Programme PHP pour compter les voyelles dans une chaîne

Quelle est la différence entre le trading pré-commercial et après-marché? Explication détaillée des différences entre le pré-commercialisation et le trading après le marché Quelle est la différence entre le trading pré-commercial et après-marché? Explication détaillée des différences entre le pré-commercialisation et le trading après le marché Mar 03, 2025 pm 11:54 PM

Quelle est la différence entre le trading pré-commercial et après-marché? Explication détaillée des différences entre le pré-commercialisation et le trading après le marché

See all articles