1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
| <?php
class FdMapping { private $redis; const MAP_UID_FD_PREFIX = 'chat_map_uid_fd:'; const MAP_FD_UID_PREFIX = 'chat_map_fd_uid:';
public function __construct($redis_host = '127.0.0.1', $redis_port = 6379) { $this->redis = new Redis(); $this->redis->connect($redis_host, $redis_port); }
public function uidBindFd($uid, $fd) { return $this->redis->sadd( self::MAP_UID_FD_PREFIX . $uid, $fd ); }
public function fdBindUid($fd, $uid) { return $this->redis->setex( self::MAP_FD_UID_PREFIX . $fd, 24 * 3600, $uid ); }
public function getUidByFd($fd) { return $this->redis->get(self::MAP_FD_UID_PREFIX . $fd); }
public function getFdsByUid($uid) { return $this->redis->sMembers(self::MAP_UID_FD_PREFIX . $uid); }
public function delFd($fd, $uid = null) { if (is_null($uid)) { $uid = $this->getUidByFd($fd); } if (!$uid) { return false; } $this->redis->srem(self::MAP_UID_FD_PREFIX . $uid, $fd); $this->redis->del(self::MAP_FD_UID_PREFIX . $fd); return true; } }
$FdMapping = new FdMapping('127.0.0.1'); $server = new swoole_websocket_server("127.0.0.1", 9502);
$server->on('open', function($server, $req) { echo "新连接: #{$req->fd}\n"; });
$server->on('message', function($server, $frame) use ($FdMapping) { echo "接收到: " . json_encode($frame->data) . "\n"; $data = json_decode($frame->data, true); switch ($data['type']) { case 'sign': $FdMapping->uidBindFd($data['uid'], $frame->fd); $FdMapping->fdBindUid($frame->fd, $data['uid']); $fds = $FdMapping->getFdsByUid($data['uid']); foreach ((array)$fds as $fd) { !$server->exist($fd) && $FdMapping->delFd($fd, $data['uid']); } $server->push( $frame->fd, json_encode([ 'status' => 1, 'msg' => '注册成功', 'token' => md5(time()), // 可用于连接合法性验证 ]) ); break; case 'msg': $data['from'] = $FdMapping->getUidByFd($frame->fd); if (!$data['from']) { $server->push( $frame->fd, json_encode([ 'status' => 0, 'msg' => '发送失败,未登入', ]) ); return; } $fds = $FdMapping->getFdsByUid($data['to']); foreach ((array) $fds as $fd) { $server->exist($fd) && $server->push( $fd, json_encode([ 'body' => $data['body'], 'from' => $data['from'], ]) ); echo "#{$fd} 推送成功\n"; } $server->push($frame->fd, json_encode(['status' => 1, 'msg' => 'sended'])); break; default: $server->push( $frame->fd, json_encode([ 'status' => 0, 'msg' => '非法请求', 'disconnect' => 1, // 告知终端请断开 ]) ); break; } });
$server->on('close', function($server, $fd) use ($FdMapping) { echo "连接断开: #{$fd}\n"; $FdMapping->delFd($fd); });
$server->start();
|