PHP   发布时间:2022-04-04  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了php socket网络编程基础知识(三):stream函数大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

说明

@H_450_2@
  • 流,算是一种对不同事物,但有相同特性的抽象封装,可能这样说并不理解,但是我们早就使用过了,例如打开文件fopen等操作,其实就是用的流,fopen('abc.txt')实际上就是fopen('file://abc.txt'),或者是与app交互用到的PHP://input获取post数据也是流的一种
  • PHP官方文档可以看Streams API for PHP Extension AuthorsStream
  • 我们只看流中与socket相关的封装,上篇我们建立一个连接需要好几个步骤,比较繁琐,而stream中对此进行了简化封装。至于流的其它包装过滤等功能,可自己去查询资料,好像是在《Modern PHP》中也有章节对此做过讲解。
  • 相关的stream函数可以参照WorkeRMAN中具体的使用场景,WorkeRMAN中没有使用上节的socket函数,而是调用的更加简洁方便的stream函数
  • 相关函数

    @H_450_2@
  • 服务端函数

    @H_450_2@
  • stream_socket_server ( String $local_socket [, int &$errno [, String &$errstr [, int $flags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN [, resource $context ]]]] ) : resource @H_450_2@
  • 创建socket服务端
  • 函数可以代替上节的socket_createsockeT_Bindsocket_listen这三个函数,例如:$socket = stream_socket_server('tcp://0.0.0.0:8000');相当于$socket = socket_create(AF_INET, SOCK_STREAM, 0);+sockeT_Bind($socket, '0.0.0.0', 8000);+socket_listen($socket);
  • $flags参数,如果是用udp通信的话,STREAM_SERVER_LISTEN 是不需要的,$context则是上下文,后面有单独的函数生成此类型,还有需要注意的是,stream_socket_serversocket_create的返回值然都是resource,但两个不能通用,socket扩展中有单独的函数来转换这两者。
  • stream_socket_accept ( resource $server_socket [, float $timeout = ini_get("default_socket_timeout") [, String &$peername ]] ) : resource @H_450_2@
  • 接收客户端的连接(udp通信时,不需要用到此函数
  • 类似socket_accept需要注意的是第一个参数,只能是stream_socket_server的返回值。
  • 客户端函数

    @H_450_2@
  • stream_socket_client ( String $remote_socket [, int &$errno [, String &$errstr [, float $timeout = ini_get("default_socket_timeout") [, int $flags = STREAM_CLIENT_CONNECT [, resource $context ]]]]] ) : resource @H_450_2@
  • 创建socket客户端,连接到服务端
  • 函数可以替代上节的socket_createsocket_connect这两个函数,例如$socket = stream_socket_client('tcp://0.0.0.0:8000'')相当于$socket = socket_create(AF_INET, SOCK_STREAM, 0);+$result = socket_connect($socket, '0.0.0.0', 8000);
  • $flags参数主要有两个选项STREAM_CLIENT_CONNECTSTREAM_CLIENT_ASYNC_CONNECT,第二个参数是设置异步,与阻塞又不太相同,挺让人费解的,而且网上也基本搜不到相关资料,当设置此参数时,将不会检测地址端口是否真的能连通,都为立即返回正常的资源resource,那如何来确定服务端是否真的能链接上呢?目前个人所知的方式是用stream_SELEct类似的多路IO复用来检测,当真正链接链接失败后内核会通知到read或者write或者except(具体通知到哪个windows和linux不一致,需要区别处理),下面的stream_SELEct函数和后期IO多路复用时会讲到。
  • 读写函数

    @H_450_2@
  • fread ( resource $handle , int $length ) : String @H_450_2@
  • 读取数据
  • fwrite ( resource $handle , String $String [, int $length ] ) : int @H_450_2@
  • 写入数据
  • 上面两个函数和我们平常读取文件一样,正如我们说的,操作文件也是操作一种流,所以方法通用
  • stream_socket_recvfrom ( resource $socket , int $length [, int $flags = 0 [, String &$address ]] ) : String @H_450_2@
  • 接收数据,最后参数是引用,用于获取远端链接的地址
  • stream_socket_sendto ( resource $socket , String $data [, int $flags = 0 [, String $address ]] ) : int @H_450_2@
  • 发送数据
  • 上面两个函数freadfwrite基本一致,但功能更多一些,$flags参数可以设置发送OOB数据,而$address参数则多是用于udp通信,由于udp通信时不使用stream_socket_accept,所以无法获取到新的resource,那就无法向指定的客户端中写数据,所以一般先用stream_socket_recvfrom获取最后引用参数$address即为客户端的地址,然后再用stream_socket_sendto设置$address,来向指定的客户端发送。
  • 其它常用函数

    @H_450_2@
  • stream_SELEct ( array &$read , array &$write , array &$except , int $tv_sec [, int $tv_usec = 0 ] ) : int @H_450_2@
  • 调用系统SELEct()相关IO模型
  • 类似上节的socket_SELEct,详细的在后面的IO模型中会总结
  • stream_seT_Blocking ( resource $stream , bool $mode ) : bool @H_450_2@
  • 设置阻塞与非阻塞,false为非阻塞,true为阻塞
  • 类似上节的socket_seT_Blocksocket_set_nonblock,但是还是有些区别的,上节我们知道socket的阻塞影响的函数为:socket_connect、socket_accept以及各种socket读写函数,而stream的阻塞影响的函数仅仅为stream相关的读写函数stream_socket_accept不受影响,一直是阻塞,stream_socket_client更不会受影响,因为stream_socket_client的返回值,才能作为stream_seT_Blocking的第一个参数,所以上方说stream_socket_client的参数flags设置为异步,算是弥补了这一问题。
  • fclose ( resource $handle ) : bool @H_450_2@
  • 关闭链接
  • stream_socket_shutdown ( resource $stream , int $how ) : bool @H_450_2@
  • 关闭链接
  • 上面两个函数功能基本一样,stream_socket_shutdown还可以控制只关闭读或者只关闭
  • socket_import_stream ( resource $stream ) : resource @H_450_2@
  • 将stream资源转为socket资源
  • socket_export_stream ( resource $socket ) : resource @H_450_2@
  • 将socket资源转为stream资源
  • 上面也提到过,socket扩展和stream两者链接产生的resource是不互通的,上面两个函数就是将两者转换的,而这两个函数是定义在上节所说的socket扩展中的,使用前需要确定socket扩展有打开
  • stream_context_create @H_450_2@
  • 上下文创建
  • stream_socket_serverstream_socket_client最后一个参数就是上下文,相关的参数需要经过此函数的组装后才能传入,我们可能早就接触过,例如我们经常用到的file_get_content可以模拟post来获取数据,就需要用到它的第三个上下文参数。
  • 示例

    @H_450_2@
  • 服务端
    $socket = stream_socket_server('tcp://127.0.0.1:8888', $errno, $errstr);
    while ($conn = stream_socket_accept($socket)) {
      fwrite($conn, "Hello\n");
      fclose($conn);
    }
    fclose($socket);
    
  • 客户端
    $socket = stream_socket_client('tcp://127.0.0.1:8888', $errorno, $errstr);
    while (!feof($socket)) {
      echo fread($socket, 1024);
    }
    fclose($socket);
    
  • 上方是简单的示例代码,更多的可以查看官网各函数下的示例代码
  • stream与socket相比是更简洁了,但是原理是一样的,同样的只能连接一个客户端的局限性并没有解决,还是需要后续的完善
  • 关联

    @H_450_2@
  • 上篇:php socket网络编程基础知识(二):socket函数
  • 下篇:php socket网络编程基础知识(四):多进程
  • 大佬总结

    以上是大佬教程为你收集整理的php socket网络编程基础知识(三):stream函数全部内容,希望文章能够帮你解决php socket网络编程基础知识(三):stream函数所遇到的程序开发问题。

    如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

    本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
    如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。
    标签: