Detailed explanation of the difference between socket_read and socket_recv in PHP, socketreadrecv
I used PHP to write a socket network service a few days ago. I was a little confused when I saw the two methods socket_read and socket_recv in the document. At first glance, they are not the same. Why do I need to give two different usages? I didn’t understand it clearly after reading the document. I figured it out after reading the source code. I’ll record it here.
Let’s take a look at the declarations of these two functions:
Copy code The code is as follows:
string socket_read ( resource $socket , int $length [, int $type = PHP_BINARY_READ ] )
int socket_recv ( resource $socket , string &$buf , int $len , int $flags )
As you can see from the declaration, one returns the received data through the execution result, and the other returns the received data through a reference. Another difference is that socket_read has one more type, and socket_recv has one more flags (which is confusing enough). Let’s take a look at the source code of socket_recv first!
Copy code The code is as follows:
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] = '
/* 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);
}
There is a lot of verbosity here, but there is actually one line that is the most crucial:
Copy code The code is as follows:
if ((retval = recv(php_sock->bsd_socket, recv_buf, len, flags)) < 1) {
As you can see, this function actually just calls the system's recv. It just processes the input parameters and the obtained results, which is easier to understand. Then let’s take a look at socket_read. Socket_read has one more $type parameter than the system’s recv function. This is also the reason why I think this function exists. As you can see from the documentation, type has two values, namely PHP_BINARY_READ and PHP_NORMAL_READ. Documentation It is written there, PHP_BINARY_READ means to directly use the system's recv method, PHP_NORMAL_READ means to read until n or r is encountered, let's take a look at the source code:
Copy code The code is as follows:
//Omit a lot of
if (type == PHP_NORMAL_READ) {
retval = php_read(php_sock, tmpbuf, length, 0);
} else {
retval = recv(php_sock->bsd_socket, tmpbuf, length, 0);
}
It can be seen that if it is PHP_NORMAL_READ mode, the behavior is actually the same as socket_recv. They both use the system's recv function. However, if it is PHP_NORMAL_READ, there is a big difference. The php_read function implemented by yourself is used. Then this php_read is used. What is it? Let’s continue looking at the source code:
Copy code The code is as follows:
*t = '