PHPの中のsocket_readとsocket_recv区別の詳細
まず、この2つの関数の宣言を見てみましょう.
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が1つ増えたrecvにはflagsが1つ増えました(混乱しています).まず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を呼び出しただけで,入力パラメータと得られた結果を処理しただけで,理解しやすいことがわかる.じゃあソケットを見てみましょうread,socket_readはシステムのrecv関数より$typeパラメータが1つ増えています.これも私がこの関数が存在する意味だと思います.ドキュメントから見ると、typeにはPHP_という2つの値があります.BINARY_READとPHP_NORMAL_READ、文書に書いてある、PHP_BINARY_READは直接システムでのrecvメソッドを表し、PHP_NORMAL_READは、または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 != '
' && *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がキー部分を指しているのか、ここでの実装は、rまたは読み出したデータの長さが指定されたmaxlenに達するまでrecvをループして呼び出すことであることがわかります.
この2つの関数は混乱していますが、ここを見るとわかるでしょう.よし寝て!