在PHPsocket_read和socket_recv之间的差异 浏览:939

几天前,我用PHP编写了一个socket网络服务。我看到有点晕的时候我在文件中看到socket_read和socket_recv两方法。乍一看,这是不一样的。为什么我需要给出两种不同的用法见文件不看太清楚,请看清楚源代码,在这里记录。

首先,看看这两个函数的声明:

复制代码代码如下所示:

字符串socket_read(资源为插座,int int类型的长度{美元,美元= php_binary_read })

国际socket_recv(资源为插座,字符串buf,int int len美元,美元的标志)



它可以从表看出,一个是返回接收到的数据通过执行的结果,而另一个是在参考的形式返回接收到的数据。另一个区别是,socket_read不仅仅是一个类型,和socket_recv不仅仅是一个标志(容易混淆)。让我们看看socket_recv首先,源一看!

复制代码代码如下所示:

php_function(socket_recv)

{

php_sock_res zval *,* buf;

char * recv_buf;

php_socket * php_sock;

用int;

长镜头,旗帜;

如果(zend_parse_parameters(zend_num_args(tsrmls_cc),rzll

返回;

}

zend_fetch_resource(php_sock,php_socket *,php_sock_res,- 1,le_socket_name,le_socket);

溢出检查

如果((镜头+ 1)< 2){

return_false;

}

recv_buf = emalloc(len + 1);

memset(recv_buf,0,len + 1);

如果((retval = recv(php_sock -> bsd_socket,recv_buf,Len,旗))<< 1){

依芙利特(recv_buf);

zval_dtor(BUF);

z_type_p(BUF)= is_null;

{人}

recv_buf { } = 0用;

重建缓冲机制 / * * /

zval_dtor(BUF);

z_strval_p(BUF)= recv_buf;

z_strlen_p(BUF)=用;

z_type_p(BUF)= is_string;

}

如果(retval = = 1){

php_socket_error(php_sock,无法从插座读

return_false;

}

return_long(用);

}



罗嗦很多,实际上有一行键:

复制代码代码如下所示:

如果((retval = recv(php_sock -> bsd_socket,recv_buf,Len,旗))<< 1){



可以看出,事实上,这个功能是调用系统的接收。它只处理输入参数,得到的结果是众所周知的。然后我们看socket_read,socket_read比一元式多参数recv函数系统,我认为这是存在的意义的功能,从文件里可以看到,有两个值,即php_binary_read和php_normal_read,文档写的,php_binary_read说直接使用接收系统的方法,php_normal_read说读,直到或者,我们看源代码:

复制代码代码如下所示:

省略了很多

如果(类型= = php_normal_read){

retval = php_read(php_sock,tmpbuf,长度,0);

{人}

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

}



你可以看到,如果是php_normal_read模式,事实上行为和socket_recv是相同的,与接收系统的功能,但如果是php_normal_read,然后是有很大区别的,用php_read函数来实现自己的php_read是干什么的我们继续看源代码:

复制代码代码如下所示:

*0;

当(t!=t!= R n < maxlen){

如果(m = 0){

++;

氮+;

} {如果(m=0)

no_read + +;

如果(非分组no_read > = 2){

返回N;

第一我总是/通,是0,所以1成为no_read

*第一关。2 no_read成为第二通,

*如果是非阻塞的,我们应该回归…

}

如果(no_read > 200){

set_errno(econnreset);

返回- 1;

}

}

如果(n<maxlen){

M = recv(袜子-> bsd_socket,((void *)T,1,标志);

}

如果(errno!= 0错误!= espipe errno!= EAGAIN){

返回- 1;

}

(0)set_errno;

}



它是拷贝的关键部分。可以看出,这里的实现是调用recv一直或遇到或读取数据的长度为指定的maxlen。

虽然这两个功能相当混乱,但在这里应该理解。
推荐文章1
广告