Home  >  Article  >  Backend Development  >  Detailed explanation of PHP SOCKET programming_PHP tutorial

Detailed explanation of PHP SOCKET programming_PHP tutorial

WBOY
WBOYOriginal
2016-07-13 09:52:58823browse

Detailed explanation of PHP SOCKET programming

This article mainly introduces the detailed explanation of PHP SOCKET programming. Friends who need it can refer to it

 1. Preliminary knowledge

It has been rare to see how many people use PHP’s socket module to do some things. Probably everyone places it within the scope of scripting languages, but in fact PHP’s socket module can do many things, including doing ftplist , http post submission, smtp submission, group package and interaction of special messages (such as smpp protocol), whois query. These are some of the more common queries.

Especially what PHP’s socket extension library can do is not much worse than C.

PHP socket connection function

1. Socket integrated in the kernel

This series of functions can only perform active connections and cannot implement port monitoring related functions. And before 4.3.0, all socket connections can only work in blocking mode.

This series of functions includes

 fsockopen, pfsockopen

For detailed information on these two functions, please refer to the user manual of php.net

They will all return a resource number. For this resource, you can use almost all functions that operate on files, such as fgets(), fwrite(), fclose(), etc. Note that all functions follow these functions. The rules of network information flow, for example:

 fread() reads up to length bytes from the file pointer handle. This function stops reading the file when length bytes have been read, EOF is reached, or (for network streams) a packet becomes available, whichever occurs first.

It can be seen that for network flows, you must pay attention to stopping when a complete packet is obtained.

 2. The socket function provided by the php extension module.

There will be a module extension=php_sockets.dll in php4.x and extension=php_sockets.so on Linux.

When this module is turned on, it means that PHP has powerful socket functions, including listen port, switching between blocking and non-blocking modes, multi-client interactive processing, etc.

For the list of functions in this series, please refer to http://www.php.net/manual/en/ref.sockets.php

After reading this list, do you think it is very rich? However, it is a pity that this module is still very young and immature in many places, and there are very few related reference documents: (

I am also researching it, so I will not discuss it in detail for the time being. I will only give you a reference article

 http://www.zend.com/pecl/tutorials/sockets.php

 2. Use PHP socket extension

Server-side code:

 ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

/**

* File name server.php

* Server-side code

*

* @author guisu.huang

* @since 2012-04-11

*

*/

// Ensure there is no timeout when connecting to the client

set_time_limit(0);

//Set IP and port number

$address = "127.0.0.1";

$port = 2046; //When debugging, you can change ports to test the program!

/**

* Create a SOCKET

* AF_INET= is ipv4. If ipv6 is used, the parameter is AF_INET6

* SOCK_STREAM is the tcp type of the socket. If it is UDP, use SOCK_DGRAM

*/

$sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() The reason for failure is:" . socket_strerror(socket_last_error()) . "/n");

//Blocking mode

socket_set_block($sock) or die("socket_set_block() failed because:" . socket_strerror(socket_last_error()) . "/n");

//Bind to socket port

$result = socket_bind($sock, $address, $port) or die("socket_bind() The reason for failure is:" . socket_strerror(socket_last_error()) . "/n");

//Start monitoring

$result = socket_listen($sock, 4) or die("socket_listen() The reason for failure is:" . socket_strerror(socket_last_error()) . "/n");

echo "OKnBinding the socket on $address:$port ... ";

echo "OKnNow ready to accept connections.nListening on the socket ... n";

do { // never stop the daemon

//It receives the connection request and calls a sub-connection Socket to process the information between the client and the server

$msgsock = socket_accept($sock) or die("socket_accept() failed: reason: " . socket_strerror(socket_last_error()) . "/n");

//Read client data

echo "Read client data n";

//The socket_read function will keep reading client data until it encounters n, t or

$buf = socket_read($msgsock, 8192);

echo "Received msg: $buf n";

//Data transmission writes the return result to the client

$msg = "welcome n";

socket_write($msgsock, $msg, strlen($msg)) or die("socket_write() failed: reason: " . socket_strerror(socket_last_error()) ."/n");

//Once the output is returned to the client, the parent/child socket should be terminated through the socket_close($msgsock) function

socket_close($msgsock);

} while (true);

socket_close($sock);

Client code:

 ?

1

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

/**

* File name:client.php

* 客户端代码

*

* @author guisu.huang

* @since 2012-04-11

*/

set_time_limit(0);

$host = "127.0.0.1";

$port = 2046;

$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)or die("Could not create socketn"); // 创建一个Socket

$connection = socket_connect($socket, $host, $port) or die("Could not connet servern"); // 连接

socket_write($socket, "hello socket") or die("Write failedn"); // 数据传送 向服务器发送消息

while ($buff = socket_read($socket, 1024, PHP_NORMAL_READ)) {

echo("Response was:" . $buff . "n");

}

socket_close($socket);

<🎜>2<🎜> <🎜>3<🎜> <🎜>4<🎜> <🎜>5<🎜> <🎜>6<🎜> <🎜>7<🎜> <🎜>8<🎜> <🎜>9<🎜> <🎜>10<🎜> <🎜>11<🎜> <🎜>12<🎜> <🎜>13<🎜> <🎜>14<🎜> <🎜>15<🎜> <🎜>16<🎜> <🎜>17<🎜> <🎜>18<🎜> <🎜>19<🎜> <🎜>20<🎜> <🎜>
<🎜> <🎜> <🎜>/**<🎜> <🎜>* File name:client.php<🎜> <🎜>* Client code<🎜> <🎜>*<🎜> <🎜>* @author guisu.huang<🎜> <🎜>* @since 2012-04-11<🎜> <🎜>*/<🎜> <🎜>set_time_limit(0);<🎜> <🎜> <🎜> <🎜>$host = "127.0.0.1";<🎜> <🎜>$port = 2046;<🎜> <🎜>$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)or die("Could not create socketn"); // Create a Socket<🎜> <🎜> <🎜> <🎜>$connection = socket_connect($socket, $host, $port) or die("Could not connet servern"); // Connection<🎜> <🎜>socket_write($socket, "hello socket") or die("Write failedn"); // Data transfer sends message to server<🎜> <🎜>while ($buff = socket_read($socket, 1024, PHP_NORMAL_READ)) {<🎜> <🎜>echo("Response was:" . $buff . "n");<🎜> <🎜>}<🎜> <🎜>socket_close($socket);<🎜> <🎜> <🎜> <🎜> <🎜> <🎜>

Use cli to start the server:

 php server.php

Pay attention to the socket_read function here:

The optional type parameter is a named constant:

PHP_BINARY_READ - Use the system recv() function. Security for reading binary data. (in PHP>default=4.1.0)

PHP_NORMAL_READ - read stops at n or r (default in PHP

 For the parameter PHP_NORMAL_READ, if the server's response result does not have n. Causes socket_read(): unable to read from socket

 3. PHP socket internal source code

Judging from PHP’s internal source code, the socket programming provided by PHP adds a layer to socket, bind, listen and other functions, making it simpler and easier to call. However, some business logic programs still need to be implemented by programmers themselves.

Next we use the source code implementation of socket_create to illustrate the internal implementation of PHP.

We mentioned earlier that PHP sockets are implemented in an extended manner. In the ext directory of the source code, we find the sockets directory. This directory stores PHP's implementation of sockets. Directly search for PHP_FUNCTION(socket_create) and find the implementation of this function in the sockets.c file. The code is as follows:

 ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

/* {{{ proto resource socket_create(int domain, int type, int protocol) U

Creates an endpoint for communication in the domain specified by domain, of type specified by type */

PHP_FUNCTION(socket_create)

{

long arg1, arg2, arg3;

php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket));

 

if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lll", &arg1, &arg2, &arg3) == FAILURE) {

efree(php_sock);

return;

}

 

if (arg1 != AF_UNIX

#if HAVE_IPV6

&& arg1 != AF_INET6

#endif

&& arg1 != AF_INET) {

php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1);

arg1 = AF_INET;

}

 

if (arg2 > 10) {

php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2);

arg2 = SOCK_STREAM;

}

 

php_sock->bsd_socket = socket(arg1, arg2, arg3);

php_sock->type = arg1;

 

if (IS_INVALID_SOCKET(php_sock)) {

SOCKETS_G(last_error) = errno;

php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, php_strerror(errno TSRMLS_CC));

efree(php_sock);

RETURN_FALSE;

}

 

php_sock->error = 0;

php_sock->blocking = 1;

1257,1-8 61%

ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket);

}

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41
/* {{{ proto resource socket_create(int domain, int type, int protocol) U Creates an endpoint for communication in the domain specified by domain, of type specified by type */ PHP_FUNCTION(socket_create) { long arg1, arg2, arg3; php_socket *php_sock = (php_socket*)emalloc(sizeof(php_socket)); if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "llll", &arg1, &arg2, &arg3) == FAILURE) { efree(php_sock); return; } if (arg1 != AF_UNIX #if HAVE_IPV6 && arg1 != AF_INET6 #endif && arg1 != AF_INET) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket domain [%ld] specified for argument 1, assuming AF_INET", arg1); arg1 = AF_INET; } if (arg2 > 10) { php_error_docref(NULL TSRMLS_CC, E_WARNING, "invalid socket type [%ld] specified for argument 2, assuming SOCK_STREAM", arg2); arg2 = SOCK_STREAM; } php_sock->bsd_socket = socket(arg1, arg2, arg3); php_sock->type = arg1; if (IS_INVALID_SOCKET(php_sock)) { SOCKETS_G(last_error) = errno; php_error_docref(NULL TSRMLS_CC, E_WARNING, "Unable to create socket [%d]: %s", errno, php_strerror(errno TSRMLS_CC)); efree(php_sock); RETURN_FALSE; } php_sock->error = 0; php_sock->blocking = 1; 1257,1-8 61% ZEND_REGISTER_RESOURCE(return_value, php_sock, le_socket); }

Zend API actually wraps the c function socket for use by PHP. In C socket programming, we use the following method to initialize the socket.

 ?

1

2

3

4

5

//初始化Socket

if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){

printf("create socket error: %s(errno: %d)n",strerror(errno),errno);

exit(0);

}

1 2 3 4 5
//Initialize Socket if( (socket_fd = socket(AF_INET, SOCK_STREAM, 0)) == -1 ){ printf("create socket error: %s(errno: %d)n",strerror(errno),errno); exit(0); }

 4. socket function

Function name description

Socket_accept() accepts a Socket connection

Socket_bind() binds the socket to an IP address and port

Socket_clear_error() clears the socket error or last error code

Socket_close() closes a socket resource

 socket_connect() starts a socket connection

 socket_create_listen() opens a socket listening on the specified port

Socket_create_pair() generates a pair of undifferentiated sockets into an array

Socket_create() generates a socket, which is equivalent to generating a socket data structure

 socket_get_option() Gets socket options

Socket_getpeername() Gets the IP address of a remote similar host

Socket_getsockname() Gets the IP address of the local socket

 socket_iovec_add() adds a new vector to a scatter/aggregate array

 socket_iovec_alloc() This function creates an iovec data structure that can be sent, received, read and written

 socket_iovec_delete() deletes an allocated iovec

Socket_iovec_fetch() returns the data of the specified iovec resource

Socket_iovec_free() releases an iovec resource

 socket_iovec_set() sets the new value of iovec data

Socket_last_error() Gets the last error code of the current socket

Socket_listen() listens to all connections from the specified socket

 socket_read() reads data of specified length

 socket_readv() reads data from the scatter/aggregate array

Socket_recv() ends the data from the socket to the cache

Socket_recvfrom() accepts data from the specified socket. If not specified, it defaults to the current socket

Socket_recvmsg() receives messages from iovec

 socket_select() Multiple selection

 socket_send() This function sends data to the connected socket

 socket_sendmsg() sends a message to socket

 socket_sendto() sends a message to the socket at the specified address

 socket_set_block() Set the socket to block mode

 socket_set_nonblock() Set the socket to non-block mode

 socket_set_option() Set socket options

Socket_shutdown() This function allows you to close the read, write, or specified socket

Socket_strerror() returns the detailed error with the specified error number

Socket_write() writes data to the socket cache

 socket_writev() writes data to the scatter/aggregate array

 5. PHP Socket simulation request

We use stream_socket to simulate:

 ?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

/**

*

* @param $data= array=array('key'=>value)

*/

function post_contents($data = array()) {

$post = $data ? http_build_query($data) : '';

$header = "POST /test/ HTTP/1.1" . "n";

$header .= "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)" . "n";

$header .= "Host: localhost" . "n";

$header .= "Accept: */*" . "n";

$header .= "Referer: http://localhost/test/" . "n";

$header .= "Content-Length: ". strlen($post) . "n";

$header .= "Content-Type: application/x-www-form-urlencoded" . "n";

$header .= "rn";

$ddd = $header . $post;

$fp = stream_socket_client("tcp://localhost:80", $errno, $errstr, 30);

$response = '';

if (!$fp) {

echo "$errstr ($errno)
n";

} else {

fwrite($fp, $ddd);

$i = 1;

while ( !feof($fp) ) {

$r = fgets($fp, 1024);

$response .= $r;

//Process this line

}

}

fclose($fp);

return $response;

}

Note that the above program may enter an infinite loop;

This is something that needs attention in PHP’s feof($fp). Let’s analyze why it enters an infinite loop.

 ?

1

2

3

4

while ( !feof($fp) ) {

$r = fgets($fp, 1024);

$response .= $r;

}

1

2

3

1

2

3

4

5

$fp = fopen("myfile.txt", "r");

while (!feof($fp)) {

$current_line = fgets($fp);

//对结果做进一步处理,防止进入死循环

}

4

while ( !feof($fp) ) {

$r = fgets($fp, 1024);

$response .= $r;

}

In fact, feof is reliable, but you must be careful when using it in conjunction with the fgets function. A common approach is:  ?

12 3 4 5
$fp = fopen("myfile.txt", "r"); while (!feof($fp)) {
$current_line = fgets($fp);
// Further process the results to prevent entering an infinite loop } When processing plain text, after fgets obtains the last line of characters, the result returned by the foef function is not TRUE. The actual operation process is as follows:  1) while() continues to loop.  2) fgets gets the string of the second to last line 3) feof returns false and enters the next loop 4) fgets gets the last row of data 5) Once the fegets function is called, the feof function still returns false. So continue executing the loop  6) fget tries to get another row, but the actual result is empty. The actual code didn't realize this and tried to process another line that didn't exist, but fgets was called and the result of feof put back was still false 7) ..... 8) Entering an infinite loop http://www.bkjia.com/PHPjc/1004548.htmlwww.bkjia.comtruehttp: //www.bkjia.com/PHPjc/1004548.htmlTechArticleDetailed explanation of PHP SOCKET programming This article mainly introduces the detailed explanation of PHP SOCKET programming. Friends who need it can refer to 1. Preparation Knowledge has always been rare to see how many people use the socket module of php to...
Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn