进程相关信息
https://segmentfault.com/a/1190000003503671
(重要)https://www.cnblogs.com/iforever/p/9039579.html
https://segmentfault.com/a/1190000008955481
单用户版本
server.php
$socket=stream_socket_server("tcp://127.0.0.1:8000",$errno,$error);
while(true){
$client=stream_socket_accept($socket);
$message="AAA-".mt_rand(1,10);
fwrite($client,$message,strlen($message));
$readStr=fread($client,2048);
printf("\n%s\n",$readStr);
//$readStr=fread($client,1024);
//printf("read:".$readStr);
fclose($client);
}
fclose($socket);client.php
$client=stream_socket_client("tcp://127.0.0.1:8000",$errno,$errstr);
if(!$client){
printf("errno:%s error:%s",$errno,$error);
}
$message="hellow".microtime(true);
fwrite($client,$message,strlen($message));
$info=fread($client,2048);
echo $info."\n";
fclose($client);第二个版本:
多客户端连接版本
server.php
$socket=stream_socket_server("tcp://127.0.0.1:8000",$errno,$error);
while(true){
$client=stream_socket_accept($socket);
//$message="AAA-".mt_rand(1,10);
//$message=fgets($client);
//fwrite($client,$message,strlen($message));
$pid=pcntl_fork();
if($pid==-1){
continue;
}elseif($pid==0){
//处理业务逻辑
while(true && $client){
$readStr=fread($client,2048);
if(empty($readStr)){
continue;
usleep(10);
}
if(trim($readStr=='exit'))
break;
printf("\n%s\n",$readStr);
fwrite($client,$readStr,strlen($readStr));
}
//$readStr=fread($client,1024);
//printf("read:".$readStr);
$myid=getmypid();
var_dump("myid {$myid}\n");
fclose($client);
}else{
pcntl_wait($status,WNOHANG);
//pcntl_wait($status,WUNTRACED);
}
usleep(1);
}
fclose($socket);客户端持续连接 wclient.php
$client=stream_socket_client("tcp://127.0.0.1:8000",$errno,$errstr);
if(!$client){
printf("errno:%s error:%s",$errno,$error);
}
while(true && $client){
printf('请输入信息:');
$message=trim(fgets(STDIN));
if($message==='exit')
break;
fwrite($client,$message,strlen($message));
$info=fread($client,2048);
printf("server say:%s".PHP_EOL,$info);
}
fclose($client);
//这以上就是php循环监听,循环发送数据以上的程序,使用了多进程的方式去同时接收多个客户端发送来的数据。
尚未实现:
客户端退出,还未能监听到。
客户端退出 ,开启的进程没有退出。
我在想,当客户端请求过来的时候,我这里只有一个进程,在处理,就ok了,可以创造多个进程,但是我们必须适用阻塞模式,
这样的情况,客户端不管发送多少来数据,都能进行接收。
且进程处理完了,就 结束了。
第三版:
多客户端连接
vm/bserver.php
#$socket=stream_socket_server("tcp://0.0.0.0:8000",$errno,$error,STREAM_SERVER_BIND | STREAM_SERVER_LISTEN);
$socket=stream_socket_server("tcp://0.0.0.0:8000",$errno,$error);
stream_set_blocking($socket,0);
$connections = [];
$read = [];
$write = null;
$except = null;
while (1) {
// look for new connections
if ($c = @stream_socket_accept($socket, empty($connections) ? -1 : 0, $peer)) {
echo $peer.' connected'.PHP_EOL;
fwrite($c, 'Hello '.$peer.PHP_EOL);
$connections[$peer] = $c;
}
// wait for any stream data
$read = $connections;
if (stream_select($read, $write, $except, 5)) {
foreach ($read as $c) {
$peer = stream_socket_get_name($c, true);
if (feof($c)) {
echo 'Connection closed '.$peer.PHP_EOL;
fclose($c);
unset($connections[$peer]);
} else {
$contents = fread($c, 1024);
echo $peer.': '.trim($contents).PHP_EOL;
}
}
}
}
fclose($socket);client.php
$client=stream_socket_client("tcp://127.0.0.1:8000",$errno,$errstr);
if(!$client){
printf("errno:%s error:%s",$errno,$error);
}
$message="hellow".microtime(true);
sleep(30);
fwrite($client,$message,strlen($message));
$info=fread($client,2048);
echo $info."\n";
fclose($client);运行实例:
[root@localhost vm]# php client.php Hello 127.0.0.1:58360 [root@localhost vm]# php bserver.php 127.0.0.1:58360 connected 127.0.0.1:58360: hellow Connection closed 127.0.0.1:58360
第四版
多进程版本
vm/server.php
$socket=stream_socket_server("tcp://127.0.0.1:8000",$errno,$error);
while(true){
$client=stream_socket_accept($socket,-1,$peer);
if(!$client)
continue;
$pid=pcntl_fork();
if($pid==-1){
continue;
}elseif($pid==0){
//处理业务逻辑
$readStr=fread($client,2048);
if(trim($readStr=='exit')|| empty($readStr)){
fclose($client);
printf("close client:%s\n",$peer);
exit;
}
printf("\n%s send data: %s\n",$peer,$readStr);
fwrite($client,strrev($readStr),strlen($readStr));
//$readStr=fread($client,1024);
//printf("read:".$readStr);
//$myid=getmypid();
//var_dump("myid {$myid}\n");
fclose($client);
printf("\nclose client:%s\n",$peer);
exit;
}else{
pcntl_wait($status,WNOHANG);
//pcntl_wait($status,WUNTRACED);
}
}
fclose($socket);client.php
$client=stream_socket_client("tcp://127.0.0.1:8000",$errno,$errstr);
if(!$client){
printf("errno:%s error:%s",$errno,$error);
}
$message="hellow".microtime(true);
fwrite($client,$message,strlen($message));
$info=fread($client,2048);
echo $info."\n";
sleep(60);
fclose($client);一般情况下,使用第三个版本吧,这样的话速度会比较块,
因为系统创建进程也是需要耗费时间的。
第五个版本:
win要用iocp啊, linux要用epoll啊 http://developer.51cto.com/art/201506/479431.htm,google就轻言细语的跟我说,高并发下的select不要用啊,效率低
$sfd = stream_socket_server ('tcp://0.0.0.0:1234', $errno, $errstr);
stream_set_blocking($sfd, 0);
$base = event_base_new();
$event = event_new();
event_set($event, $sfd, EV_READ | EV_PERSIST, 'ev_accept', $base);
event_base_set($event, $base);
event_add($event);
event_base_loop($base);
function ev_accept($socket, $flag, $base)
{
$connection = stream_socket_accept($socket);
stream_set_blocking($connection, 0);
$buffer = event_buffer_new($connection, 'ev_read', NULL, 'ev_error', $connection);
event_buffer_base_set($buffer, $base);
event_buffer_timeout_set($buffer, 30, 30);
event_buffer_watermark_set($buffer, EV_READ, 0, 0xffffff);
event_buffer_priority_set($buffer, 10);
event_buffer_enable($buffer, EV_READ | EV_PERSIST);
}
function ev_error($buffer, $error, $connection)
{
event_buffer_disable($buffer, EV_READ | EV_WRITE);
event_buffer_free($buffer);
fclose($connection);
}
function ev_read($buffer, $connection)
{
$read = event_buffer_read($buffer, 256);
//do something....
}socket_select() 这个选择是有个数限制的,1024个
把程序源码上传上来:以备后用
以至于上边还是有部分瑕疵,比如说 使用 fgets 是否可以读取数据?
多客户端实现的原理是什么?为什么使用stream_select
有时间搞明白吧