• PHP Socket实现websocket(四)Select函数


    int select(int maxfdp,fd_set *readfds,fd_set *writefds,fd_set *errorfds,struct timeval *timeout);

    /*参数列表
    int maxfdp是一个整数值,是指集合中所有文件描述符的范围,即所有文件描述符的最大值加1,不能错!在Windows中这
    个参数的值无所谓,可以设置不正确。
      
    fd_set *readfds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的读变化的,
    即我们关心是否可以从这些文件中读取数据了,如果这个集合中有一个文件可读,select就会返回一个大于0的值,表示有文
    件可读,如果没有可读的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误返
    回负值。可以传入NULL值,表示不关心任何文件的读变化。
      
    fd_set *writefds是指向fd_set结构的指针,这个集合中应该包括文件描述符,我们是要监视这些文件描述符的写变化的,
    即我们关心是否可以向这些文件中写入数据了,如果这个集合中有一个文件可写,select就会返回一个大于0的值,表示有文
    件可写,如果没有可写的文件,则根据timeout参数再判断是否超时,若超出timeout的时间,select返回0,若发生错误
    返回负值。可以传入NULL值,表示不关心任何文件的写变化。
      
    fd_set *errorfds同上面两个参数的意图,用来监视文件错误异常。
      
    struct timeval* timeout是select的超时时间,这个参数至关重要,它可以使select处于三种状态:
    第一,若将NULL以形参传入,即不传入时间结构,就是将select置于阻塞状态,一定等到监视文件描述符集合中某个文件描
    述符发生变化为止;
    第二,若将时间值设为0秒0毫秒,就变成一个纯粹的非阻塞函数,不管文件描述符是否有变化,都立刻返回继续执行,文件无
    变化返回0,有变化返回一个正值;
    第三,timeout的值大于0,这就是等待的超时时间,即 select在timeout时间内阻塞,超时时间之内有事件到来就返回了,
    否则在超时后不管怎样一定返回,返回值同上述。
    */

    /*
    返回值: 

    负值:select错误

    正值:某些文件可读写或出错

    0:等待超时,没有可读写或错误的文件

    PHP的socket_select函数也是调用系统的select函数实现的。PHP中socket_select()函数传入的read和write数组是引用传入的,所以每次调用socket_select()后
    read和write或者except数组中会包含最新的可以使用的资源数组。传入的是要监视的,而调用socket_select后得到的是可以用的。
    http://php.net/manual/zh/function.socket-select.php

    服务器端:
     1 <?php 
     2     $port = 1212;
     3 
     4     $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
     5 
     6     socket_set_option($sock, SOL_SOCKET, SO_REUSEADDR, 1);
     7 
     8     //绑定所有进入该端口的连接
     9     socket_bind($sock, 0, $port);
    10 
    11     socket_listen($sock);
    12 
    13     $clients = array($sock);
    14 
    15     while(true)
    16     {
    17         //socket_select对读写套子节的数字是引用,为了保证clients不被改变,拷贝一份。
    18         $read = $clients;
    19         $write = null;
    20         $expect = null;
    21 
    22         //当没有套字节可以读写继续等待, 第四个参数为null为阻塞, 为0位非阻塞, 为 >0 为等待时间
    23         if(socket_select($read, $write, $expect, 0) < 1)
    24         {
    25             continue;
    26         }
    27 
    28         //查看是否有新的连接
    29         if(in_array($sock, $read))
    30         {
    31             $clients[] = $newsock = socket_accept($sock);
    32             socket_write($newsock, 'there are '.(count($clients) - 1)." clients connected
    ");
    33             socket_getpeername($newsock, $ip);
    34             echo "
    new client $ip
    ";
    35             $key = array_search($sock, $read);
    36             unset($read[$key]);
    37         }
    38 
    39         //便利所有可读取数据套子节然后广播消息
    40         foreach ($read as $read_sock)
    41         {
    42             $data = @socket_read($read_sock, 1024);
    43             if($data === false)
    44             {
    45                 $key = array_search($read_sock, $clients);
    46                 socket_getpeername($clients[$key], $ip);
    47                 unset($clients[$key]);
    48                 echo "client $ip disconnected
    ";
    49                 continue;
    50             }
    51             $data = trim($data);
    52             if(!empty($data))
    53             {
    54                 echo $data;
    55                 foreach($clients as $send_sock)
    56                 {
    57                     if($send_sock == $sock || $send_sock == $read_sock)
    58                     {
    59                         continue;
    60                     }
    61                     socket_write($send_sock, $data);
    62                 }
    63             }            
    64         }
    65     }
    66 
    67     socket_close($sock);

    客户端:

     1 <?php 
     2     set_time_limit(0);
     3     $client = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
     4     socket_connect($client, '127.0.0.1', 1212);
     5     socket_write($client, "Form Client client.php 
    ");
     6     while(true)
     7     {
     8         $response = socket_read($client, 1024);
     9         echo $response;
    10     }
    11     socket_close($client);





  • 相关阅读:
    个人作业1——四则运算题目生成程序
    软件工程的实践项目课程的自我目标
    个人附加作业
    个人作业3——个人总结(Alpha阶段)
    结对编程2——单元测试
    个人作业二——英语学习APP 案例分析
    结对编程 (201421123002,201421123006,201421123007)
    四则运算
    软件工程的实践项目课程的自我目标
    个人作业3——个人总结(Alpha阶段)
  • 原文地址:https://www.cnblogs.com/yangxunwu1992/p/5564454.html
Copyright © 2020-2023  润新知