php
如何实现基于事件驱动的网络编程当客户端发送数据到服务端,服务端返回相同信息。php
保持链接编程
说明
接下来的全部代码仅用于简单的小demo
生产环境须要考虑代码的严谨性。bash
简单的接受数据并返回网络
<?php $socket = stream_socket_server("tcp://0.0.0.0:8000"); $conn = stream_socket_accept($socket); $info = fgets($conn,1024); fwrite($conn, $info."\n"); ?>
$ telnet 0.0.0.0 8000 Trying 0.0.0.0... Connected to 0.0.0.0. Escape character is '^]'. hello //客户端输入 hello //这个是服务端回显的 Connection closed by foreign host.
上面的例子中,服务端在接收到客户端数据后会返回相同信息,而后链接会被关闭。没法保持链接。?。socket
$socket = stream_socket_server("tcp://0.0.0.0:8000"); while($conn = stream_socket_accept($socket)){ while($info = fread($conn,1024)){ fwrite($conn,$info); } }
上面的例子
简单的接受数据并返回
保持运行
缺点是同时只能处理一个链接!!!!!?tcp
$socket = stream_socket_server("tcp://0.0.0.0:8000"); while($conn = stream_socket_accept($socket)){ if(pcntl_fork()){ while($info = fread($conn,1024)){ fwrite($conn,$info); } } }
这里实际上fork了n个子进程去处理n个请求。
可是使用fork进程的方式很差,很很差。
若是10万个链接,岂不是要10万个进程???oh,no!!oop
基于libevent的实现,很完美!!!?code
<?php $server = stream_socket_server("tcp://0.0.0.0:8000"); $event = event_new(); $base = event_base_new(); $events = []; event_set($event,$server,EV_READ|EV_PERSIST,function()use($server){ global $base,$events; $conn = stream_socket_accept($server); $event = event_new(); event_set($event,$conn,EV_READ|EV_PERSIST,function()use($conn){ $info = fread($conn,1024); if(strlen($info)>0){ fwrite($conn,$info); } }); event_base_set($event,$base); event_add($event); $events[] = $event; }); event_base_set($event,$base); event_add($event); event_base_loop($base);