This article mainly introduces PHPSOCKET programming details. For more information, see
1. prerequisites
I have never seen how many people use the socket module of php to do some things. maybe everyone has positioned it within the scope of the script language, but in fact, the php socket module can do a lot of things, including ftplist, http post submission, smtp submission, group packets, interaction of special packets (such as smpp protocol), and whois query. These are common queries.
In particular, php's socket extension library can do nothing worse than c.
Php socket connection function
1. socket integrated into the kernel
This series of functions only support active connections and cannot implement functions related to Port listening. In addition, before 4.3.0, all socket connections can only work in blocking mode.
This series of functions includes
Fsockopen, pfsockopen
The specific information of these two functions can be found in the php.net user manual.
They will return a resource number. for this resource, almost all functions that operate on the file can be used to perform operations such as fgets (), fwrite (), and fclose () note that all functions follow the rules when facing network information flows. for example:
Fread () reads a maximum of length bytes from the file pointer handle. This function reads the length of several bytes, or stops reading files when it reaches the EOF, or (for network streams) when a package is available, depending on the first situation.
It can be seen that for network streams, you must note that a complete package is obtained and the package is stopped.
2. socket functions provided by the php extension module.
Php4.x and later have such a module extension = php_sockets.dll, which is an extension = php_sockets.so in Linux.
When this module is enabled, php has powerful socket functions, including listen port, blocking and non-blocking mode switching, and multi-client interactive processing.
For a list of functions in this series, see http://www.php.net/manual/en/ref.sockets.php.
I think this list is very rich? However, it is a pity that this module is still very young and has many immature places, and there are very few references :(
I am also working on it, so I will not discuss it for the moment. I will only give you a reference article.
Http://www.zend.com/pecl/tutorials/sockets.php
2. use PHP socket extension
Server code:
<? Php/*** File name server. php * server code ** @ author guisu. huang * @ since 2012-04-11 ** // ensure that the set_time_limit (0) does not time out during client connection; // Set the IP address and port number $ address = "127.0.0.1"; $ port = 2046; // during debugging, you can change the port to test the program! /*** Create a SOCKET * AF_INET = is ipv4. If ipv6 is used, the parameter AF_INET6 * SOCK_STREAM is the tcp type of socket, for UDP, use SOCK_DGRAM */$ sock = socket_create (AF_INET, SOCK_STREAM, SOL_TCP) or die ("socket_create :". socket_strerror (socket_last_error ()). "/n"); // The cause of the socket_set_block ($ sock) or die ("socket_set_block () failure in the blocking mode is :". socket_strerror (socket_last_error ()). "/n"); // bind to the socket port $ result = socket_bind ($ sock, $ address, $ port) or die ("socket_bind () the cause of failure is :". socket_strerror (socket_last_error ()). "/n"); // start listening $ result = socket_listen ($ sock, 4) or die ("socket_listen () the cause of failure is :". socket_strerror (socket_last_error ()). "/n"); echo "OK \ nBinding the socket on $ address: $ port... "; echo" OK \ nNow ready to accept connections. \ nListening on the socket... \ n "; do {// never stop the daemon // it receives connection requests and calls a sub-connection Socket to process 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 reads client data until \ n, \ t, or character is met. the PHP script regards this character as an input Terminator. $ buf = socket_read ($ msgsock, 8192); echo "Received msg: $ buf \ n"; // data transmission writes the returned 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 terminate socket_close ($ msgsock) through the socket_close ($ msgsock) function );} while (true); socket_close ($ sock );
Client code:
<? Php/*** 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 ("cocould not create socket \ n"); // create a Socket $ connection = socket_connect ($ socket, $ host, $ port) or die ("cocould not connet server \ n"); // Connect socket_write ($ socket, "hello socket") or die ("Write failed \ n "); // send the message while ($ buff = socket_read ($ socket, 1024, PHP_NORMAL_READ) {echo ("Response was :". $ buff. "\ n");} socket_close ($ socket );
Start the server using cli:
Php server. php
Note the socket_read function here:
An 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-stop at n or (default value in PHP <= 4.0.6)
For the PHP_NORMAL_READ parameter, if the server's response result does not have n. Cause socket_read (): unable to read from socket
3. PHP socket internal source code
From the perspective of the internal source code of PHP, the socket programming provided by PHP adds a layer to functions such as socket, bind, and listen to make it simpler and more convenient to call. However, some business logic programs must be implemented by programmers themselves.
The following describes the internal implementation of PHP using the socket_create source code.
We have mentioned above that php socket is implemented in an extended way. In the ext Directory of the source code, find the sockets directory. This directory stores PHP's socket implementation. Directly search for PHP_FUNCTION (socket_create) and find the implementation of this function in the sockets. c file. The code is as follows:
/* {{{ 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); }
The Zend API actually wraps the c function socket for PHP. In c's socket programming, we use the following method to initialize the socket.
// 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 functions
Function name description
Socket_accept () accepts a Socket connection
Socket_bind () binds the socket to an IP address and port.
Socket_clear_error () clears socket errors or the final error code
Socket_close () closes a socket resource
Socket_connect () starts a socket connection
Socket_create_listen () opens a socket listener on the specified port.
Socket_create_pair () generates a pair of non-differentiated sockets into an array.
Socket_create () generates a socket, which is equivalent to the data structure of a socket.
Socket_get_option () obtain the socket option
Socket_getpeername () obtains the IP address of a remote host similar to that of a remote host.
Socket_getsockname () gets the IP address of the local socket
Socket_iovec_add () add a new vector to a scattered/aggregated array
Socket_iovec_alloc () this function creates an iovec data structure that can send and receive read/write data.
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 () obtains the final error code of the current socket.
Socket_listen () listens to all connections from the specified socket
Socket_read () reads data of the specified length
Socket_readv () reads data from scattered/aggregate arrays
Socket_recv () ends data from the socket to the cache
Socket_recvfrom () accepts data from the specified socket. If no value is specified, the current socket is used by default.
Socket_recvmsg () receives messages from iovec
Socket_select () multi-path selection
Socket_send () this function sends data to the connected socket
Socket_sendmsg () sends a message to the socket
Socket_sendto () sends a message to the socket of the specified address
Socket_set_block () is set to block mode in socket
Set the socket in socket_set_nonblock () to non-block mode.
Socket_set_option () sets socket options
Socket_shutdown () function allows you to close the read, write, or specified socket
Socket_strerror () returns a detailed error of the specified error number.
Socket_write () writes data to the socket cache
Socket_writev () writes data to a distributed/aggregate array
5. PHP Socket request simulation
We use stream_socket to simulate:
/***** @ Param $ data = 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. = "\ r \ n"; $ 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 programs may enter an endless loop;
This PHP feof ($ fp) should be noted. let's analyze why it enters an endless loop.
while ( !feof($fp) ) { $r = fgets($fp, 1024); $response .= $r; }
In fact, feof is reliable, but you must be careful when using it with the fgets function. A common practice is:
$ Fp = fopen ("myfile.txt", "r"); while (! Feof ($ fp) {$ current_line = fgets ($ fp); // further process the result to prevent an endless 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 calculation process is as follows:
1) while () continues the loop.
2) fgets gets the string from the second to the last line
3) feof returns false, entering the next loop
4) fgets obtains the last row of data
5) once the fegets function is called, the feof function returns false. So continue to execute the loop
6) fget tries to get another row, but the actual result is null. The actual code does not realize this and tries to process a line that does not exist at all. However, if fgets is called, feof still returns false.
7 ).....
8) enters the endless loop