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) < 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);
}

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

代码如下:

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。

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

(0)

相关推荐

  • php中使用Curl、socket、file_get_contents三种方法POST提交数据

    抓取远程内容,之前一直都在用file_get_content函数,其实早就知道有curl这么一个好东西的存在,但是看了一眼后感觉使用颇有些复杂,没有file_get_content那么简单,再就是需求也不大,所以没有学习使用curl.直到最近,要做一个网页小偷程序的时候才发现file_get_content已经完全不能满足需求了.我觉得,在读取远程内容的时候,file_get_content除了使用比curl便捷以外,其他都没有curl好. php中curl和file_get_content的一

  • PHP中Socket连接及读写数据超时问题分析

    本文实例讲述了PHP中Socket连接及读写数据超时问题.分享给大家供大家参考,具体如下: 虽然PHP中对fsockopen()方法有连接socket的超时参数,但是没有类似C中的连接成功后对数据的读写超时参数设置.没关系,PHP中对stream提供了一系列的方法以防止超时 stream_set_blocking( $fp , false ) 设置数据流为阻塞模式,以防止数据没读完就退出 如果模式为 false, 给定的 socket 描述符将切换到非块模式, 如果为 true, 则切换到块模式

  • PHP实现Socket服务器的代码

    <?php ob_implicit_flush(); set_time_limit(0); $address = "192.40.7.93";//换成你自己的地址 $port = 10000; if(($socket = socket_create(AF_INET,SOCK_STREAM,SOL_TCP)) == false)  echo "错误(socket_create):".socket_strerror(socket_last_error()).&qu

  • 基于PHP Socket配置以及实例的详细介绍

    2个php测试文件server.php 复制代码 代码如下: <?php     //phpinfo();//确保在连接客户端时不会超时set_time_limit(0);$ip = '127.0.0.1';$port = 1935;/* +------------------------------- *    @socket通信整个过程 +------------------------------- *    @socket_create *    @socket_bind *    @s

  • 使用swoole扩展php websocket示例

    复制代码 代码如下: <?phpdefine('DEBUG', 'on');define("WEBPATH", str_replace("\\","/", __DIR__));require __DIR__ . '/../libs/lib_config.php'; class WebSocket extends Swoole\Network\Protocol\WebSocket{    /**     * 下线时,通知所有人     */ 

  • php中curl、fsocket、file_get_content三个函数的使用比较

    抓取远程内容,之前一直都在用file_get_content函数,其实早就知道有curl这么一个好东西的存在,但是看了一眼后感觉使用颇有些复杂,没有file_get_content那么简单,再就是需求也不大,所以没有学习使用curl.直到最近,要做一个网页小偷程序的时候才发现file_get_content已经完全不能满足需求了.我觉得,在读取远程内容的时候,file_get_content除了使用比curl便捷以外,其他都没有curl好. php中curl和file_get_content的一

  • php socket方式提交的post详解

    <?  /*  ** POST报文到主机  */  function PostToHost($url, $data) {  $url = parse_url($url);  if (!$url) return "couldn\'t parse url";  if (!isset($url[\'port\'])) { $url[\'port\'] = ""; }  if (!isset($url[\'query\'])) { $url[\'query\'] = 

  • 深入浅出php socket编程

    对TCP/IP.UDP.Socket编程这些词你不会很陌生吧?随着网络技术的发展,这些词充斥着我们的耳朵.那么我想问: 1.什么是TCP/IP.UDP? 2.Socket在哪里呢? 3.Socket是什么呢? 4.你会使用它们吗? 什么是TCP/IP.UDP? TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,是一个工业标准的协议集,它是为广域网(WANs)设计的. UDP(User Data Protocol

  • php socket客户端及服务器端应用实例

    经常有朋友会对php的socket应用充满疑惑,本文就以实例代码作一讲解,希望能对初学php的朋友起到一点帮助作用 具体代码如下: 1.服务器端代码: <?php class SocketServer{ private $_port='9000'; private $_address='127.0.0.1'; private $_client_socket_list=array(); public function __set($name,$val){ $this--->$name=$val;

  • php获取远程图片的两种 CURL方式和sockets方式获取远程图片

    方式1:sockets 复制代码 代码如下: $a = "http://jb51.net/content/uploadfile/201106/thum-f3ccdd27d2000e3f9255a7e3e2c4880020110622095243.jpg"; $local = 'socket1.gif'; $aa = getImg($a,$local); /* *@ 完整的图片地址 *@ 要存储的文件名 */ function getImg( $url = "", $

  • PHP异步调用socket实现代码

    PHP异步调用实现方式 浏览器和服务器之间只一种面向无连接的HTTP协议进行通讯的,面向无连接的程序的特点是客户端请求服务端,服务端根据请求输出相应的程序,不能保持持久连接. 这样就出现了一个问题,一个客户端的相应服务端可能执行1秒也有可能执行1分钟,这样浏览器就会一直处于等待状态,如果程序执行缓慢,用户可能就没耐心关掉了浏览器. 而有的时候我们不需要关心程序执行的结果,没有必要这样浪费时间和耐心等待,那我们就要想出办法让程序不收等待在后台静默执行. 比如现在有一个场景,给1000个用户发送一封

  • php使用socket编程示例

    2个php测试文件server.php 复制代码 代码如下: <?php//phpinfo();//确保在连接客户端时不会超时set_time_limit(0); $ip = '127.0.0.1';$port = 1935; /* +------------------------------- *    @socket通信整个过程 +------------------------------- *    @socket_create *    @socket_bind *    @sock

  • php与java通过socket通信的实现代码

    demo实现的简单功能是,接受PHP端写入的字符串,然后原样返回给输出端.代码如下: 复制代码 代码如下: import java.io.*; import java.net.*; public class Server { public static void main(String[] args) throws IOException{   System.out.println("Server started !\n");   ServerSocket server=new Ser

  • php使用websocket示例详解

    下面我画了一个图演示 client 和 server 之间建立 websocket 连接时握手部分,这个部分在 node 中可以十分轻松的完成,因为 node 提供的 net 模块已经对 socket 套接字做了封装处理,开发者使用的时候只需要考虑数据的交互而不用处理连接的建立.而 php 没有,从 socket 的连接.建立.绑定.监听等,这些都需要我们自己去操作,所以有必要拿出来再说一说. ① 和 ② 实际上就是一个 HTTP 的请求和响应,只不过我们在处理的过程中我们拿到的是没有经过解析的

随机推荐