额,这应该是菜鸟级别的问题,但是看了文档我还是无从下手。
回复内容: 额,这应该是菜鸟级别的问题,但是看了文档我还是无从下手。
php的socket是资源类型:
resource(4) of type (socket),也就是每个socket句柄都一个样子。。
而linux c socket fd是个int整数,每个都是不同数字。
原生php做不到“主动对已经连接过来的,用户uid=123的那个用户,推送一条消息”,
但借助swoole利用linux c实现的socket,我们可以实现“主动对已经连接过来的,用户uid=123的那个用户,推送一条消息”。
这里我们可以用system v最简单的share memory来进程间共享数据ipc,维护一个用户id与其socket连接的映射表。
代码如下:
set(array( 'worker_num' => 8, //工作进程数量 'daemonize' => false, //是否作为守护进程));$shmid = shm_attach(getmypid(), 1024*66); # allocate 66kb for shared memorydefine(shared_uid_connection_map, 12);shm_put_var($shmid,shared_uid_connection_map, []);$serv->on('connect', function ($serv, $fd) use($shmid) { echo client:connect.\n;});$serv->on('receive', function ($serv, $fd, $from_id, $data) use($shmid) { $serv->send($fd, 'swoole: '.$data); // $serv->close($fd); $trimdata = trim($data); if ($trimdata == 'i am lucky man') { $map = shm_get_var($shmid,shared_uid_connection_map); $map[] = $fd; #$map[$uidfromdata] = $fd; shm_put_var($shmid,shared_uid_connection_map, $map); } if ($trimdata == 'broadcast to lucky man') { $map = shm_get_var($shmid,shared_uid_connection_map); // var_dump($map); $ $map is array whose valuse is int $fd foreach($map as $fd) { $serv->send($fd, some body broadcast to you luck man); } } # broadcast to all users // $start_fd = 0; // while(true) // { // $conn_list = $serv->connection_list($start_fd, 10); // if($conn_list===false or count($conn_list) === 0) // { // echo finish\n; // break; // } // $start_fd = end($conn_list); // var_dump($conn_list); // foreach($conn_list as $fd) // { // $serv->send($fd, broadcast); // } // } // var_dump($serv->connections); // foreach ($serv->connections as $k => $v) { // $lk = [$k,$v]; // var_dump($lk); // }});$serv->on('close', function ($serv, $fd) { echo client: close.\n;});$serv->start();
然后就可以开n个客户端,来测试下代码,比如我开3个telnet 127.0.0.1 1024,最后一个发消息给服务器i am lucky man,第一个再对服务器发broadcast to lucky man,那么第三个就会收到some body broadcast to you luck man,实现对特定用户发送消息。
就是这么简单,
swoole大法好,异步io+多进程 也是最成熟的结局方案(致敬nginx)
哈哈哈
uid只是你识别的uid而已,socket链接到服务,都有一个唯一的id,你要对客户端发送消息只能通过这个唯一的id,你可以在这两者之间做个映射,那就可以了。