PHP socket programming detailed _php skills

Source: Internet
Author: User
Tags http post php server php script set socket socket error port number zend

1. Preliminary knowledge

has been rarely seen how many people use PHP socket module to do something, probably everyone positioning it in the context of scripting language, but in fact, PHP socket module can do a lot of things, including doing ftplist,http post submission, SMTP submission, Group packages and carry out special message interactions (e.g. SMPP protocol), WHOIS queries. These are the more common queries.

In particular, the PHP socket extension library can do things that are simply not much worse than c.

PHP Socket Connection function

1, integrated in the kernel socket

This series of functions can only do the active connection can not implement port monitoring related functions. And all socket connections can only work in blocking mode before 4.3.0.
This series of functions includes
Fsockopen,pfsockopen
The specific information of these two functions can be queried php.net user manual
They all return a resource number. For this resource, you can manipulate it with almost any function of the file operation such as Fgets (), fwrite (), fclose (), etc. note that all functions follow the laws of these functions in the face of network flow, for example:
Fread () reads up to length bytes from the file pointer handle. The function stops reading the file when a package is available, either by reading the length byte number, or by reaching EOF, or (for a network stream), depending on which situation is first encountered.
You can see that for the network flow you must pay attention to a complete package to stop.

2, PHP expansion module with the socket function.

Php4.x has such a module after Extension=php_sockets.dll,linux is a extension=php_sockets.so.
When this module is opened it means PHP has a powerful socket function, including listen ports, blocking and non-blocking mode switching, multi-client interactive processing, etc.
A list of functions for this series see http://www.php.net/manual/en/ref.sockets.php
Did you see the list and think it's very rich? Unfortunately, the module is still very young and many places are immature, and the relevant reference documentation is very small: (
I'm also working on it, so I'm not going to discuss it for the time being, just give you a reference article

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

2. Use PHP Socket extension

Server-side code:

<?php/** * File name server.php * Server-side code * * @author Guisu.huang * @since 2012-04-11 *///To ensure customer connection 
End will not timeout set_time_limit (0); 
Set IP and port number $address = "127.0.0.1"; $port = 2046; 
When debugging, you can change the port to test the program! /** * Create a socket * af_inet= is IPv4 if IPv6, then the parameter is Af_inet6 * Sock_stream is the TCP type of the socket, if UDP is the use of sock_dgram/$sock = s Ocket_create (Af_inet, Sock_stream, sol_tcp) or Die ("socket_create () the reason for the failure is:". Socket_strerror (Socket_last_error ()). 
"/n"); The reason for the blocking mode Socket_set_block ($sock) or Die ("Socket_set_block ()" Failure is: ". Socket_strerror (Socket_last_error ()). 
"/n"); Binding to the socket port $result = Socket_bind ($sock, $address, $port) or Die ("Socket_bind ()) failed because of:". Socket_strerror (Socket_last_error ()). 
"/n"); Start listening $result = Socket_listen ($sock, 4) or Die ("Socket_listen ()) failed because of:". 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 {//NeverStop the daemon//it receives the connection request and invokes a child 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 \ n"; The Socket_read function reads the client data until it encounters a \n,\t or a character. 
 The PHP script regards this character as the input terminator. 
 $buf = Socket_read ($msgsock, 8192); 
  
 echo "Received msg: $buf \ n"; 
 The data transfer 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 terminate the Socket_close ($msgsock) by 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 ("could not create socket\n"); Create a socket 
 
$connection = Socket_connect ($socket, $host, $port) or die ("could not connet server\n");//Connect 
Soc Ket_write ($socket, "hello socket") or Die ("Write failed\n"); The data transfer sends a message to the server while 
($buff = Socket_read ($socket, 1024, php_normal_read)) { 
 echo ("Response is:"). $buff. "\ n"); 
} 
Socket_close ($socket); 

To start the server by using the CLI method:

PHP server.php

Note here the Socket_read function:
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-stop in \ n or \ r (default in PHP <= 4.0.6)

For parameter php_normal_read, if the server's response results are not \ n. Cause socket_read (): Unable to read from socket

3. PHP Socket Internal Source code

From the internal source of PHP, PHP provides the socket programming is in Socket,bind,listen and other functions outside the addition of a layer to make it more simple and convenient to call. But some business logic programs need to be implemented by programmers themselves.
Below we use the Socket_create source code implementation to explain the internal implementation of PHP.
We have mentioned that the PHP socket is implemented in an extended way. In the source of the Ext directory, we find the sockets directory. This directory holds the PHP implementation of the socket. A direct search for php_function (socket_create) found the implementation of this function in the sockets.c file. As shown in the following code:

/* {{{proto resource socket_create (int domain, int type, int protocol) U creates a endpoint for communication in the 
  Domain specified by domain, the 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", ARG 
    1); 
  Arg1 = af_inet; } if (Arg2 >) {php_error_docref (NULL tsrmls_cc, e_warning, invalid socket type [%LD] specified for Argum 
    ENT 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 use in PHP. In C socket programming, we use the following method to initialize the socket.

Initializes the 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 the last error code
Socket_close () closes a socket resource
Socket_connect () Start a socket connection
Socket_create_listen () opens a socket listener on the specified port
Socket_create_pair () produces a pair of no differential sockets into an array
Socket_create () produces a socket, which is equivalent to generating a socket data structure
Socket_get_option () Get socket option
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 a IOVEC data structure capable of sending and receiving read and write
Socket_iovec_delete () deletes an assigned Iovec
Socket_iovec_fetch () returns the data for the specified Iovec resource
Socket_iovec_free () frees a Iovec resource
Socket_iovec_set () sets the Iovec data new value
Socket_last_error () Gets the last error code for the current socket
Socket_listen () listens for all connections by the specified socket
Socket_read () reads the specified length of data
SOCKET_READV () reads data coming from a scatter/aggregate array
SOCKET_RECV () end data from socket to cache
Socket_recvfrom () accepts data from the specified socket and, if not specified, the default current socket
Socket_recvmsg () received a message from Iovec
Socket_select () multi-channel selection
Socket_send () This function sends data to the connected socket
SOCKET_SENDMSG () Send message to socket
Socket_sendto () sends a message to the socket at the specified address
Socket_set_block () is set to block mode in the socket
Socket_set_nonblock () socket is set to not block mode
Socket_set_option () Set socket options
Socket_shutdown () This function allows you to close a read, write, or specified socket
Socket_strerror () returns a detailed error for the specified error number
Socket_write () write data to the socket cache
Socket_writev () write data to a scatter/aggregate array

5. PHP Socket Simulation Request

We use Stream_socket to simulate:

/** 
 * 
 * @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. = "\ r \ n"; 
 $DDD = $header. $post; 
 $fp = Stream_socket_client ("tcp://localhost:80", $errno, $errstr); 
 $response = '; 
 if (! $fp) { 
  echo "$errstr ($errno) <br/>\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 procedure may go into a dead loop;

This PHP feof ($fp) needs to be noticed, and we'll analyze why we get into the dead loop.

while (!feof ($fp)) { 
 $r = fgets ($fp, 1024); 
 $response. = $r; 
} 

In fact, feof is reliable, but it must be careful when combined with the Fgets function. A common practice is to:

$fp = fopen ("MyFile.txt", "R"); 
while (!feof ($fp)) { 
 $current _line = fgets ($fp); 
 Further processing of the results to prevent entering the dead loop 
}

When working with plain text, the result returned by the FOEF function is not true after Fgets gets the last line of characters. The actual operation process is as follows:

1 while () continues the loop.

2) Fgets Gets the string from the penultimate line

3) feof return False, go to Next loop

4) Fgets get last line of data

5 Once the Fegets function is invoked, the Feof function still returns false. So go ahead and execute the loop.

6) Fget tried to get another line, but the actual result was empty. The actual code is unaware of this, trying to handle a line that doesn't exist at all, but the fgets is called, and the result of feof is still false

7) ...

8) into the dead cycle

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.