专栏首页PHP饭米粒玩转 PHP 网络编程全套阻塞与非阻塞 IO

玩转 PHP 网络编程全套阻塞与非阻塞 IO

扯蛋

上一篇我们撸了不咋样的TCP server,然后还扯了半天的口水,现在呢我们来继续撸客户端

TCP Server

$ip = "0.0.0.0";
$port = $argv[1];
$sockefd = socket_create(AF_INET,SOCK_STREAM,0);
socket_bind($sockefd,$ip,$port);
socket_listen($sockefd,5);
while (1){
    $connfd = socket_accept($sockefd);
    if ($connfd){
        socket_write($connfd,"hello,php 是世界上是好的语言");
        while (1){
 if(($recv=socket_read($connfd,4098,PHP_BINARY_READ))){
                socket_write($connfd,"server:$recv");
            }
        }
    }

}
socket_close($sockefd);
socket_close($connfd);

TCP Client

$ip = $argv[1];
$port = $argv[2];
$sockfd = socket_create(AF_INET,SOCK_STREAM,0);
socket_connect($sockfd,$ip,$port);
while (1){
    if(($recv = socket_read($sockfd,4098))){
        echo $recv;
    }
    $data = fread(STDIN,2014);
    if ($data){
        socket_write($sockfd,$data,strlen($data));
    }
}
socket_close($sockfd);

现在我们来分别运行server/client来简单的通信

ok,以上通信没问题

现在用telent工具来折腾下它

启动服务时 我们看到客户端与服务器端是可以正常来往通信的,我们看到服务器运行时它是处于accept阻塞进程的。 连接服务时

客户连接时,accept立马执行【进程被唤醒】同时返回一个TCP连接,并且这个连接通过为5,程序就执行到socket_read处阻塞了,同时我们列出/proc/PID/fd时生成了如下文件

当客户发送字符串”hello”时socket_read函数执行并读取到内容及读取的数据长度

以上说了半天,就是在告诉你 socket_accept,socket_read,socket_write这些函数是阻塞IO!!!

阻塞IO与非阻塞IO

我觉得光解释不行的,你得撸上代码去体验 阻塞IO【阻塞的文件描述符】: 执行系统调用【读写请求】时不会立即返回,需要等待就绪事件【读写事件】发生,操作系统会让程序挂起来【SLEEPING】 非阻塞IO: 执行系统调用后,程序会立即返回,如果事件没有发生会返回-1,同时会带有出错信息如EAGAIN,EWOULDBLOCK,EINPROGRESS

那我们下面来写一个非阻塞的TCP服务

非阻塞的IO【非阻塞的文件描述符】

设置非阻塞的函数 ps:在c语言里一般用fcntl去控制文件描述符

socket_set_nonblock($socket);
stream_set_blocking( resource $stream , int $mode )
$ip = "0.0.0.0";
$port = $argv[1];
$sockefd = socket_create(AF_INET,SOCK_STREAM,0);

socket_bind($sockefd,$ip,$port);
socket_listen($sockefd,5);

$counter = 0;
while (1){

    $counter++;
    //$sockfd 我们最好让它阻塞,不然立马返回的话 $connfd可不是资源即连接就会导致socket_set_nonblock报错的
    $connfd = socket_accept($sockefd);
    echo "accept \n"; 
    //得到客户端连接设置为非阻塞IO模式
    socket_set_nonblock($connfd);
    if ($connfd){
        socket_write($connfd,"hello,php 是世界上是好的语言");
        echo "write once\n";  
        //要是这里不加while它就跑一次完事了
        //加上while【忙轮询】就是让socket_read一直不停的问有没有数据
        while (1){
            if(($recv=socket_read($connfd,4098,PHP_BINARY_READ))){
                socket_write($connfd,"server:$recv");
            }
            //上面的socket_read不管有没有读取到数据
            //都立马返回并且执行echo
            //如果是阻塞模式,则该句就得等上面的socket_read运行了这里才执行,否则就得等,等的结果就是SLEEP,cpu就会干其它事情了
            echo "不阻塞一直不停的执行socket_read问内核有没有数据\n";
            sleep(1);
        }
    }

}
socket_close($sockefd);
socket_close($connfd);

测试的结果【非常建议动手撸,不然没法体会阻塞与非阻塞】

同样的我们不设置为非阻塞模式时,它默认是阻塞IO

本文分享自微信公众号 - PHP饭米粒(phpfamily)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-05-14

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 012. NIO 非阻塞网络编程

    山海散人
  • Java网络编程--NIO非阻塞网络编程

    从Java1.4开始,为了替代Java IO和网络相关的API,提高程序的运行速度,Java提供了新的IO操作非阻塞的API即Java NIO。NIO中有三大核...

    CodingDiray
  • php 多进程编程父进程的阻塞与非阻塞实例分析

    本文实例讲述了php 多进程编程父进程的阻塞与非阻塞。分享给大家供大家参考,具体如下:

    砸漏
  • python 网络编程学习 非阻塞soc

    SocketServer简化了网络服务器的编写。它有4个类:TCPServer,UDPServer,UnixStreamServer,UnixDatagramS...

    py3study
  • 服务端 I/O 性能大比拼:Node、PHP、Java、Go哪家强?

    理解应用程序的输入/输出(I/O)模型,意味着其在计划处理负载与残酷的实际使用场景之间的差异。若应用程序比较小,也没有服务于很高的负载,也许它影响甚微。但随着应...

    Java技术栈
  • 漫谈Swoole协程与异步IO

    初次接触Swoole的PHP开发者多少都会有点雾里看花的感觉,看不清本质。一部分PHP开发者并不清楚Swoole是什么,只是觉得很牛掰就想用了,这种行为无异于写...

    桶哥
  • 服务端 I/O 性能大比拼:Node、PHP、Java 和 Go

    理解应用程序的输入/输出(I/O)模型,意味着其在计划处理负载与残酷的实际使用场景之间的差异。若应用程序比较小,也没有服务于很高的负载,也许它影响甚微。但随着应...

    哲洛不闹
  • 一文读懂高性能网络编程中的I/O模型

    随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力。本文(和下篇《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》)旨...

    JackJiang
  • 一文读懂高性能网络编程中的I/O模型

    随着互联网的发展,面对海量用户高并发业务,传统的阻塞式的服务端架构模式已经无能为力。本文(和下篇《高性能网络编程(六):一文读懂高性能网络编程中的线程模型》)旨...

    JackJiang

扫码关注云+社区

领取腾讯云代金券