Giter Site home page Giter Site logo

elarity / advanced-php Goto Github PK

View Code? Open in Web Editor NEW
1.3K 58.0 257.0 144 KB

最近打算写一些php一些偏微妙的教程,比如关于多进程、socket等相关,都是自己的一些感悟心得

License: Apache License 2.0

php socket process stream pcntl

advanced-php's Issues

李哥,请教个14章里的代码问题,就是我改了下代码,客户端telnet发送quit后,服务端关闭这个链接,这个客户端再连接时,发送的消息服务端接收不到了,代码和演示在下面

server.php
`<?php
$host = '0.0.0.0';
$port = 9999;
$fd = socket_create( AF_INET, SOCK_STREAM, SOL_TCP );
socket_bind( $fd, $host, $port );
socket_listen( $fd );
// 注意,将“监听socket”设置为非阻塞模式
socket_set_nonblock( $fd );

$event_arr = [];
$conn_arr = [];

echo PHP_EOL.PHP_EOL."欢迎来到ti-chat聊天室!发言注意遵守当地法律法规!".PHP_EOL;
echo " tcp://{$host}:{$port}".PHP_EOL;

$event_base = new EventBase();

$event = new Event( $event_base, $fd, Event::READ | Event::PERSIST, function( $fd )
{
// 使用全局的event_arr 和 conn_arr
global $event_arr,$conn_arr,$event_base;
// 非阻塞模式下,注意accpet的写法会稍微特殊一些。如果不想这么写,请往前面添加@符号,不过不建议这种写法
if( ( $conn = socket_accept( $fd ) ) != false ){
echo date('Y-m-d H:i:s').':欢迎'.intval( $conn ).'来到聊天室'.PHP_EOL;
// 将连接socket也设置为非阻塞模式
socket_set_nonblock( $conn );
// 此处值得注意,我们需要将连接socket保存到数组中去
$conn_arr[ intval( $conn ) ] = $conn;
$event = new Event( $event_base, $conn, Event::READ | Event::PERSIST, function( $conn ) use( $event_arr )
{
global $conn_arr;
$buffer = trim(socket_read( $conn, 65535 ));
$msg = intval( $conn ).'说 : '.$buffer.PHP_EOL;
if($buffer=='quit'){
unset($conn_arr[intval($conn)]);
unset($event_arr[intval($conn)]);
socket_close($conn);
$buffer="我 走了";
$msg = intval( $conn ).'说 : '.$buffer.PHP_EOL;
}
echo $msg.PHP_EOL;
foreach( $conn_arr as $conn_key => $conn_item ){
if( $conn != $conn_item ){
socket_write( $conn_item, $msg, strlen( $msg ) );
}
}
if($buffer=='quit'){
unset($conn);
}
}, $conn );
$event->add();
// 此处值得注意,我们需要将事件本身存储到全局数组中,如果不保存,连接会话会丢失,也就是说服务端和客户端将无法保持持久会话
$event_arr[ intval( $conn ) ] = $event;
}
}, $fd );
$event->add();
$event_base->loop();`

演示:
problem

疑问:图中的6发送quit到server,server断开了连接,然后在这个客户端窗口再次连接产生7,然后发送消息,为何server和其它客户端都接收不到7的消息了呢,其它客户端发的消息,它能正常收到,需要调整哪里呢?

进程daemon化样例中的判断有问题

// 将当前子进程提升会会话组组长 这是至关重要的一步 
if ( ! posix_setsid() ) {
    exit( ' setsid error. ' );
}

这个地方的判断是不是应该是posix_setsid()<0, 官方文档上说:错误时返回-1

另外:这个样例里,为什么需要二次fork?麻烦指导一下

posix_setsid() 返回 -1 时是错误的

你好,我看到手册里 posix_setsid() 函数的返回值

Returns the session id, or -1 on errors.

下边这样的写法是不是错误的:

if (!posix_setsid()) {
    exit(' setsid error. ');
}

是不是应该这样:

if (-1 === posix_setsid()) {
    exit(' setsid error. ');
}

关于 php xxx.php & 关闭终端会退出

首先,感谢你的知识分享,我想请教一个问题
你提到一个知识点是,单独的在命令后面加 & 符号 在终端退出的时候,进程也会推到
我的环境是:本地虚拟机+xshell
当我在xshell中用命令启动进程后,我立即关闭xshell,这个时候我的程序还在跑。
我就有点懵逼了。还请先生指点一二。

运行了你的代码,没有成为僵尸进程。

    $pid = pcntl_fork();
	if( $pid > 0 ){
	    // 下面这个函数可以更改php进程的名称
		cli_set_process_title('php father process');
		
		// 返回值保存在$wait_result中
		// $pid参数表示 子进程的进程ID
		// 子进程状态则保存在了参数$status中
		// 将第三个option参数设置为常量WNOHANG,则可以避免主进程阻塞挂起,此处父进程将立即返回继续往下执行剩下的代码
		$wait_result = pcntl_waitpid( $pid, $status, WNOHANG );
		var_dump( $wait_result );
		var_dump( $status );
		echo "不阻塞,运行到这里".PHP_EOL;
		
	    // 让主进程休息60秒钟
	    sleep(60);
		
	} else if( 0 == $pid ) {
	    cli_set_process_title('php child process');
		// 让子进程休息10秒钟,但是进程结束后,父进程不对子进程做任何处理工作,这样这个子进程就会变成僵尸进程
		sleep(10);
	} else {
	    exit('fork error.'.PHP_EOL);
	}

我运行试了这段代码,没有成为僵尸进程,是怎么回事。
image

event 案例中的event_arr不太明白 请教下

在 案例 14. PHP [socket初探中](https://github.com/elarity/advanced-php/blob/master/14.%20PHP%20socket%E5%88%9D%E6%8E%A2%20---%20%E5%90%AB%E7%9D%80%E6%B3%AA%E4%B9%9F%E8%A6%81%E7%A3%95%E5%AE%8Clibevent%EF%BC%88%E4%B8%89%EF%BC%89.md)
聊天代码里
// 这里值得注意,我们声明两个数组用来保存 事件 和 连接socket $event_arr = []; $conn_arr = []; // 此处值得注意,我们需要将事件本身存储到全局数组中,如果不保存,连接会话会丢失,也就是说服务端和客户端将无法保持持久会话 $event_arr[ intval( $conn ) ] = $event;
这里的event_arr 感觉完全没有应到到其他地方 只是将event保存了到数组并没有对数组进行操作

提点小建议

auxBSD风格,建议作者以后ps aux不要再带-了,虽然现在的系统做了兼容处理也能显示正确内容,但是看着比较别扭。

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.