Home  >  Article  >  Backend Development  >  Write basic Socket programs in PHP

Write basic Socket programs in PHP

藏色散人
藏色散人forward
2019-11-18 14:11:033657browse

Warning to young people

Utopias are useless. Personal ability comes from every day's hard work, rather than reaching the sky in one step. Don't be afraid of any new knowledge. One day, every drop of water will penetrate the stone. It will be dark and the flowers will be bright.

My purpose

Because in my future study, I may use network content, but at the same time, many coders who write PHP have never written sockets program, but I must have heard of it, and I must have heard of the word network programming, so for future learning, I plan to briefly explain the relevant knowledge here. This blog post comes with an example program, and the code is hosted on Code Cloud (php-socket-base-code: https://gitee.com/obamajs/php-socket-base-code), you only need to download it, configure the relevant environment, and follow the instructions to run it.

Environment configuration

Socket programming needs to enable the socket extension of php. The computer I use is windows, so here you only need to open the php.ini file and find this line Just remove the comments

extension=sockets

Official Document

The official address of php socket programming is: php socket (https://www.php.net/manual/ en/book.sockets.php)

Server-side programming

Socket programming follows certain programming steps. These steps are indispensable. Client and server Programming is different, let's look at the server first.

Write basic Socket programs in PHP

Create socket

Sockets are system resources. We first call the socket_create method (refer to the official documentation: https: //www.php.net/manual/en/function.socket-create.php), the call is as follows:

$this->socket_handle = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
if (!$this->socket_handle) {
      //创建失败抛出异常,socket_last_error获取最后一次socket操作错误码,socket_strerror打印出对应错误码所对应的可读性描述
     throw new Exception(socket_strerror(socket_last_error($this->socket_handle)));
} else {
          echo "create socket successful\n";
}

The first parameter specifies whether the current socket uses ipv4 or ipv6, if so If the former is the case, then pass AF_INET, otherwise AF_INET6. Of course, there is another type, which is AF_UNIX. This will not be discussed for the time being. We generally choose AF_INET (ipv6 is not very popular).

The second parameter specifies the type of protocol. Generally, TCP or UDP is selected. TCP is a reliable stream transmission (the most widely used in life, ensuring reliability and security), while UDP is not. , this parameter generally selects TCP.

The third one is SOL_TCP if you selected TCP before, otherwise it is SOL_UDP.

Binding address and port number

Because a host may have multiple IP addresses, you need to specify which one your socket is listening to. Commonly used The value is 127.0.0.1, or listening to all addresses 0.0.0.0. So someone here may not understand. What is the difference between 127.0.0.1 and 0.0.0.0? 127.0.0.1 is just a loopback address and can only be used for local access. To put it bluntly, you can use it yourself. Because this IP is not open to the outside world, no one can access this address, so if your server address is set to 127.0. 0.1, if others want to access, they can only go to shit.

0.0.0.0 is not strictly an IP address. It means that all the IP addresses of this machine are mine, haha.

Understood the above, let’s look at the code for this call

if (!socket_bind($this->socket_handle, $this->addr, $this->port)) {
         throw new Exception(socket_strerror(socket_last_error($this->socket_handle)));
    } else {
         echo "bind addr successful\n";
 }

Is it very simple? The first parameter is the result returned by socket_create, and the second parameter is the address. The above is already As mentioned, the third parameter is the port number.

Listening socket

After the above steps, we just created a socket and bound the port number and address to it, but what about the system? Do you know it's a listening socket? So, our work is not done yet, so we have to tell it. Don't tell me that you are in a good relationship with the system! ! !

if (!socket_listen($this->socket_handle, $this->back_log)) {
      throw new Exception(socket_strerror(socket_last_error($this->socket_handle)));
  } else {
      echo "socket  listen successful\n";
 }

The second parameter is worth explaining. Please listen to me in detail. For every process in the Linux system, the system maintains a queue of pending sockets (first in, first out). , it has to be said on a first-come, first-served basis), it takes time for the upper-level program to process the business logic, so just wait. So what is the size of this queue set to? Its value is the second parameter, so can I set it to a large value? Saonian, are you thinking too much? This value is different in different systems. Don’t say I’m fooling you. See below.

The maximum number passed to the backlog parameter highly depends on the underlying platform. On Linux, it is silently truncated to SOMAXCONN. On win32, if passed SOMAXCONN, the underlying service provider responsible for the socket will set the backlog to a maximum reasonable value. There is no standard provision to find out the actual backlog value on this platform.

You don’t have to care about the precise data of this value, it is meaningless.

Everything is ready, all we need is Dongfeng

After the above operation, we can start to accept connections from the client, and this function is even simpler

$client_socket_handle = socket_accept($this->socket_handle);

The return value of this function is also a socket handle, so you can read and write it. In the current example program, what we do is very simple, so simple that you can doubt your life.

 $client_socket_handle = socket_accept($this->socket_handle);
        if (!$client_socket_handle) {
            echo "socket_accept call failed\n";
            exit(1);
        } else {
            while (true) {
                $bytes_num = socket_recv($client_socket_handle, $buffer, 100, 0);
                if (!$bytes_num) {
                    echo "socket_recv  failed\n";
                    exit(1);
                } else {
                    echo "content from client:" . $buffer . "\n";
                }
            }
        }

Reading socket

Taking the above example, we use socket_recv to read the content from the client. This function is very simple, and the function prototype is as follows

socket_recv ( resource $socket , string &$buf , int $len , int $flags ) : int

The read content will be returned in the second parameter. The second parameter passes the number of characters we want to read. The fourth parameter can be directly set to 0. The return value of this function is the actual read value. The number of bytes taken.

Client Programming

客户端相对于服务端来说,就很简单了,流程如下

Write basic Socket programs in PHP

创建套接字前面已经讲过了,不再详述,客户端只需要连接服务器即可,函数为 socket_create,我们来看一哈在当前的例子中,我们是如何调用的。

if (!socket_connect($this->socket_handle, $this->server_addr, $this->server_port)) {
            echo socket_strerror(socket_last_error($this->socket_handle)) . "\n";
            exit(1);
        } else {
            while (true) {
                $data = fgets(STDIN);
                //如果用户输入quit,那么退出程序
                if (strcmp($data, "quit") == 0) {
                    break;
                }
                socket_write($this->socket_handle, $data);
            }
        }

该函数只需要指定服务器的地址和端口号即可,参数是不是很简单

练习实例

在讲解基本函数调用的时候,我就把自带程序的核心部分,复制出来了,如果要完整的程序,这里是地址(php-socket-base-code:https://gitee.com/obamajs/php-socket-base-code),代码非常简单,再次提醒,这些代码完全是用于给大家讲解基本的 socket 变成操作,为大家以后的学习打下基础,那么如何使用这个例子程序呢?

进入到命令行,开启服务器程序

php TcpServer.php,

打开另外一个命令行界面,

php TcpClient.php,

在客户端界面,输入任何文本,再输入回车,再切换到服务器界面,您将会看到客户端输入的内容

在笔者的电脑上操作实例截图如下:

Write basic Socket programs in PHP

The above is the detailed content of Write basic Socket programs in PHP. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:learnku.com. If there is any infringement, please contact admin@php.cn delete