• 用php入门网络编程


    学习思路

    以下是我对学习网络编程的一个简单的学习思路,之后我将会按照这个计划去逐步学习网络编程相关的知识。

    1. step 1. 原生php实现TCP Server -> 原生php实现http协议 -> 掌握tcpdump的使用 -> 深刻理解tcp连接过程
    2. step 2. 原生php实现多进程webserver 2.1 引入I/O多路复用 2.2 引入php协程(yield) 2.3 对比 I/O多路复用版本 和 协程版本的性能差异
    3. step 3. 实现简单的go web框架
    4. step 4. php c扩展实现简单的webserver

    什么我会选择用php去学习网络编程?因为对于我来说,php算是最熟悉的,其次php相对来说简单些,同时php自身也有相应的函数支持。

    我们今天先开始第一部分的学习。

    正文

    我们先简单回顾下php作为后端语言的常见的交互方式过程:

    client –(protocol:http)–> nginx –(protocol:fastcgi)–> php-fpm –(interface:sapi)–> php

    在这里nginx充当的web server和反向代理server的角色,把http协议转换成了fastcgi协议。看到这里有些小伙伴可能会说了:“如果php自己直接处理http请求,不就可以不用nginx&php-fpm了么?”遗憾的是原生php木有实现http协议(是吧,欢迎纠错)。

    然后可能又有小伙伴说:“原生php不是支持tcp协议么?nginx把http请求代理成tcp协议不就可以不用php-fpm了吗。”,嗯,是的,没错。这位小伙伴的描述的交互过程如下

    client –(protocol:http)–> nginx –(protocol:tcp)–> php

    这样看起来是没啥问题,很不错的想法,但是理论来说还是没有实现http协议,接收到的内容应该还是一坨字符串。我们马上来试一下:

    STEP 1: 起一个NGINX服务
    STEP 2: PHP简单实现一个TCP SERVER,简单的代码如下
    <?php
    
    $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    
    socket_bind($server, '127.0.0.1', '8889');
    socket_listen($server);
    
    while (true) {
        $client = socket_accept($server);
        if (! $client) {
            continue;
        }
        $request = socket_read($client, 1024);
        // 查看接收到的内容
        var_dump($request);
        socket_close($client);
    }

     访问结果

     所以我们就需要实现http协议,既然都实现了http协议,那就可以直接使用http作为web server了。

    client –(protocol:http)–> php

    接着我们看看如何用php创建一个简单的TCP Server过程如下:

    主要涉及的PHP函数如下

    socket_create
    
    socket_listen
    
    socket_accept
    
    socket_recv || socket_read
    
    socket_write
    
    socket_close

    代码如下

    <?php
    
    $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
    
    socket_bind($server, '127.0.0.1', '8889');
    
    socket_listen($server);
    
    while (true) {
        // accept
        $client = socket_accept($server);
        if (! $client) {
            continue;
        }
        $request = socket_read($client, 1024);
        socket_close($client);
        echo socket_strerror(socket_last_error($server)) . "
    ";
    }

    没毛病,TCP Server起来了。

    原生PHP实现HTTP协议

    上面简单的TCP Server基本出来了,我们需要让php直接成为一个Web Server,想一想Web Server是基于HTTP协议的,HTTP协议又是基于TCP协议实现的。也就是说我们在上面的TCP Server基础上实现下HTTP协议即可。我们改进下流程图加入HTTP部分(橙黄色),如下

    实现HTTP协议的过程其实就是:

    1. 能读懂发来请求的信息
    2. 能返回给浏览器等客户端它们能懂的信息

    协议无非就是双方协定好的规范,一样在HTTP/1.1中 请求&响应的格式基本如下

     请求:

    <HTTP Method> <url> <HTTP Version>
    <KEY>:<VALUE>
    
    ...
    
    

    响应:

    <HTTP Version> <HTTP Status> <HTTP Status Description>
    <KEY>:<VALUE>
    
    ...
    
    

     所以简单来说,我们的php代码只要按照上面的规范解析和返回出对应的内容即可,简单的代码例子如下:

    <?php
        $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
        socket_bind($server, '127.0.0.1', '8889');
        socket_listen($server);
        $http = new HttpProtocol();
        
        while(true){
            $client = socket_accept($server);
            if (!$client){
                continue;
            }
            $request = socket_read($client, 1024);
            $http->response("hello word");
            socket_write($client, $http->resposeData);
            socket_close($client);
        }
        class HttpProtocol {
             private $header=[
                "http"=>"HTTP/1.1 200 OK",
                "content-type" => "Content-Type:text/html",
                "server" => "Server: php/0.0.1",
            ];
            public  $resposeData="";
            public function response($msg){
                $count = count($this->header);
                $finalData="";
                foreach($this->header as $key => $value){
                    $finalData.=$value."
    ";
                }
                $this->resposeData = $finalData."
    ".$msg;
            }
        }
    
    ?>

    运行代码:

    结果展示:

     参考网址[http://tigerb.cn/2018/11/24/php-network-programming/]

  • 相关阅读:
    [Python] Array Attributes of Numpy lib
    《火球——UML大战需求分析》(第2章 耗尽脑汁的需求分析工作)——2.1 需求分析面面观
    UVA 10201 Adventures in Moving
    《史蒂夫·乔布斯传》官方正式中文版电子书(高清晰完整版)
    为什么要用BitSet
    sed 技巧一例:特定位置插入
    Mac+IPAD上使用wireshark抓包
    【经验谈】XmlSerializer的坑
    HTML语言简单回顾
    不可思议的每日培训(1)——日复一日的每日分享
  • 原文地址:https://www.cnblogs.com/zh718594493/p/14173046.html
Copyright © 2020-2023  润新知