Linux 使用 PHP Ev 擴(kuò)展,監(jiān)聽 socket。
這邊有兩個(gè)遞進(jìn)的監(jiān)聽:
監(jiān)聽客戶端連接
客戶端連接后,監(jiān)聽客戶端進(jìn)行收發(fā)數(shù)據(jù)
具體實(shí)現(xiàn)代碼如下:
<?php
$tcp = "127.0.0.1:9005";
$count = 2;
$pids = [];
// 端口多進(jìn)程監(jiān)聽
for ($i = 0; $i < $count; ++$i)
{
$pid = pcntl_fork();
if ($pid < 0) {
exit('生成子進(jìn)程失敗\n');
} else if ($pid > 0) {
// 父進(jìn)程
$pids[] = $pid;
} else {
var_dump("產(chǎn)生子進(jìn)程 {$i}");
// 創(chuàng)建資源流上下文
$context = stream_context_create([
'socket' => [
//
'backlog' => 102400
]
]);
// 設(shè)置端口重用
stream_context_set_option($context , 'socket' , 'so_reuseport' , 1);
// 監(jiān)聽客戶端鏈接 + 設(shè)置端口重用
$server = stream_socket_server($tcp , $errno , $errstr , STREAM_SERVER_BIND | STREAM_SERVER_LISTEN , $context);
$clients = [];
// 如果資源可讀,讀取,并且一直監(jiān)聽
$ev = new EvIo($server , Ev::READ , function($watcher) use($clients , $server){
var_dump("接收到客戶端鏈接");
var_dump($watcher->fd === $server);
// $client = stream_socket_accept($watcher->fd);
$client = stream_socket_accept($server);
$clients[] = $client;
// 設(shè)置資源阻塞模式
stream_set_blocking($client , false);
// 事件監(jiān)聽
$ev = new EvIO($client , Ev::READ | Ev::WRITE , function($watcher) use($client , $clients){
var_dump($watcher->fd === $client);
var_dump("客戶端資源可讀!!");
});
var_dump("監(jiān)聽客戶端數(shù)據(jù)收發(fā)已經(jīng)就緒");
});
// 開始事件監(jiān)聽!
Ev::run();
// 不要進(jìn)入父進(jìn)程領(lǐng)域
exit;
}
}
foreach ($pids as $v)
{
pcntl_waitpid($v , $status , WUNTRACED);
}
var_dump("所有進(jìn)程都已經(jīng)退出");
運(yùn)行后發(fā)現(xiàn),如果有客戶端連接,則觸發(fā)回調(diào)函數(shù),但是,如果該客戶端發(fā)送了數(shù)據(jù)到服務(wù)器,卻沒有觸發(fā)回調(diào)。
不知道該如何破解??
1 回答

qq_遁去的一_1
TA貢獻(xiàn)1725條經(jīng)驗(yàn) 獲得超8個(gè)贊
EvIo
有些特性:
- 同作用域下,同類事件會(huì)相互覆蓋,后面定義的覆蓋前面的
- 嵌套事件,需要再次執(zhí)行
Ev::run
才會(huì)觸發(fā),再次調(diào)用Ev::run
后事件的執(zhí)行不可預(yù)測(cè)。
基于上面兩個(gè),我發(fā)現(xiàn)了一個(gè)特殊的現(xiàn)象:
function login($fd , $flag , $callback , $args){
return new EvIo($fd , $flag , $callback , $args);
}
// 這種方式定義多個(gè)重復(fù)事件,都會(huì)觸發(fā) ..
// 無語,但是目前就是用這種方式投入使用的
$one = login($socket , Ev::READ , null , null);
$two = login($socket , Ev::READ , null , null);
// 跑進(jìn)程
Ev::run();
- 1 回答
- 0 關(guān)注
- 355 瀏覽
添加回答
舉報(bào)
0/150
提交
取消