stream_set_blocking阻塞和非阻塞到底怎么理解?????

zhuxiaoyu

如何用代码直观的展现出来????

4074 1 1
1个回答

blogdaren

伪代码如下:

<?php
$main_socket = stream_socket_server("tcp://0.0.0.0:8888", $error_code, $error_msg)  or die('create server failed');

while(1)
{
    set_error_handler(function(){}); 
    $new_socket = stream_socket_accept($main_socket, 5, $remote_address);
    restore_error_handler();

    if(!$new_socket) continue;

    //屏蔽或开启本行代码进行调试
    //stream_set_blocking($new_socket, 0);

    if(pcntl_fork() == 0)
    {
        while(1)
        {
            $pid = posix_getpid();
            $request = fread($new_socket, 8192);
            var_dump($request);
            $msg = trim($request);
            if(!empty($msg))
            {
                $response = "{$pid} | {$remote_address} | {$msg}" . PHP_EOL;
                fwrite($new_socket, $response);
            }
        }
        exit(0);
    }
} 

区别就在于: 
1、当 socket处于阻塞模式时,比如:fread系统调用必须等待socket有数据返回,即进程因系统调用阻塞;相反若处于非阻塞模式,内核不管socket数据有没有准备好,都会立即返回给进程。
2、另外进程阻塞和socket阻塞不是一个概念,进程阻塞是因为系统调用所致,socket是否阻塞只是说明socket上事件是不是可以内核即刻处理。

  • zhuxiaoyu 2018-11-06

    我原来用IO select一直模拟不出来,我stream_socket_server创建了一个main资源,然后我用stream_select监听,然后我发起一个tcp请求,请求创建的时候为main的read发生改变,然后我在tcp写字符串,这样才在tcp_new_connection的read发生操作,所以说IO select就是非阻塞的么???如果是的话,为啥还要设置资源为非阻塞啊????因为资源发生读操作的时候才调read

  • blogdaren 2018-11-06

    1、select是系统调用,必然会阻塞进程的,和socket是否阻塞并没有关系,我第2点备注了呢。
    2、这里的IO就是针对socket的网络IO,是否是阻塞的,正是你题示所问的问题。
    3、socket之所以设置成非阻塞,是为了同一个进程里可以更多的处理更多的tcp连接,这正是 select、poll 或者 epoll等多路复用模型能够处理高并发的原因所在。

  • zhuxiaoyu 2018-11-06

    大佬,我stream_socket_server创建了一个main资源,然后我设置这个main为阻塞状态,新接受的新请求资源也设置了阻塞,一个进程还是能同时接受两个tcp资源

  • zhuxiaoyu 2018-11-06

    @614:IO select

  • zhuxiaoyu 2018-11-06

    @614:我还是没太理解为什么main资源要非阻塞

  • blogdaren 2018-11-06

    1、select 模型原本就是为解决传统阻塞模型中单进程只能阻塞处理一个tcp连接的问题,自然是单进程内可以接受多个连接呢。
    2、select 模型无论是main资源还是accept后的资源,这些socket句柄设置成非阻塞的目的主要在于:避免同一个进程在轮询处理多个tcp连接IO时进程阻塞的问题,进程内阻塞会影响后续IO的处理。

  • zhuxiaoyu 2018-11-07

    @614:多谢 听君一席话胜读十年书 可否加个微信

  • blogdaren 2018-11-07

    OK,私信你了

年代过于久远,无法发表回答
🔝