swoole学习笔记

swoole学习笔记

swoole流程图

学习当中的问题和疑问收集

最重要的一个问题:
假设该用户正在线上, 而swoole\websocket\server进程被强制关闭, 存储在redis中的用户iD连接池中的用户ID来不及清除(原因是:程序的机制是socket断开连接后, on close的回掉中才会删除该用户在redis中的ID), 而被保留下来. 等到程序再次运行的时候, 使用On message进行发送消息时, 遍历redis中的用户ID, 但其实有很多用户ID是之前运行的程序遗留下来的用户ID. 这时候就会报错Notice;
我想到的解决办法是, 
1. swoole 一直检测redis中某一个Key存在的话, 就删除userid同时close掉进程.如果想要停掉该进程则,直接在redis中写入该key.
2.  利用进程间的通信,用另一个进程调用swoole的close方法, 来关闭进程.



使用如下方式进行的swoole下的socket聊天室,功能;
1. 据称,单个进程有最大连接限制, 一旦超过连接限制, 会造成进程的自动回收, 即close, 关闭该进程, 这个该怎么解决.
2. 研究一下,swoole的多进程, 进程间的关系.
3. 接收图片和接受消息时header中的关系, 以及如何判断用户发送的是图片信息还是文字信息,如何处理用户发送的视频音频和图片

swooleWebsocket不能通过访问页面的形式开启, 只能通过cli的形式激活.

简易代码,利用redis作为连接池,群发消息

<?PHP

$ip = '127.0.0.1';
$port = '9999';
# 连接本地的服务
$redis = new Redis();  
$redis->connect('127.0.0.1', 6379);  

/**
 * 我的代码
 */
$serv = new Swoole\Websocket\Server($ip, $port);

 # 连接时触发的事件
$serv->on('Open', function($server, $req)  use($redis) {
	echo "成功连接connection open: ".$req->fd. "\n";
	# 用户组的连接池
	$redis->hset('Users', $req->fd, $req->fd);
});

# 收到消息触发的事件
$serv->on('Message', function($server, $frame) use($redis){
	echo "用户message: ".$frame->data. "\n";
	# 获取用户列表
	$users = $redis->hgetall('Users');
	# 循环发送数据
	foreach ($users as $k1=>$v1){
		# 判断该用户是否还在线
		if (!$server->exist($v1)) {
			echo  $v1.": 用户退出This user out\n";
			$redis->hDel('Users', $v1);
			continue;
		}
		$server->push($v1, json_encode(['name' => $frame->fd, 'content' => strip_tags($frame->data)]));
	}
});

# 关闭连接时触发的事件
$serv->on('Close', function($server, $fd) use($redis){
	# 断开连接时清除该用户key, 不在为该用户发送消息
	$redis->hdel('Users', $fd);
	echo "连接关闭connection close: ".$fd. "\n";
});

# 开始运行
$serv->start();

/**
 * 该程序问题收集: 当client和SERVER正在通信时,突然停掉进程, 会导致,正在通信的clientId没有被close掉,clientId依然存储在redis中未被删除.
 * 下次启动进程,在on(Message)发送数据时, 该用户的ID依然被遍历发送, 导致Notice错误, 因为此时该用户实际上并未连接, 该ID已经失效. 
 * 应该想一个办法, 当进程被关闭时, 清空redis中hash表上User的所有数据, 销毁所有的ID, 不知道封装成一个类, 使用 __destruct魔术方法好不好使.
 */
  • On Open函数中$req内容
class Swoole\Http\Request#8 (3) {
  public $fd =>
  int(1)
  public $header =>
  array(12) {
    'host' =>
    string(14) "127.0.0.1:9999"
    'connection' =>
    string(7) "Upgrade"
    'pragma' =>
    string(8) "no-cache"
    'cache-control' =>
    string(8) "no-cache"
    'upgrade' =>
    string(9) "websocket"
    'origin' =>
    string(20) "http://test.demo.com"
    'sec-websocket-version' =>
    string(2) "13"
    'user-agent' =>
    string(120) "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36"
    'accept-encoding' =>
    string(23) "gzip, deflate, sdch, br"
    'accept-language' =>
    string(35) "zh-CN,zh;q=0.8,en-US;q=0.6,en;q=0.4"
    'sec-websocket-key' =>
    string(24) "8uuhzMSyitKPFYcvb33XVA=="
    'sec-websocket-extensions' =>
    string(42) "permessage-deflate; client_max_window_bits"
  }
  public $server =>
  array(10) {
    'request_method' =>
    string(3) "GET"
    'request_uri' =>
    string(1) "/"
    'path_info' =>
    string(1) "/"
    'request_time' =>
    int(1492708365)
    'request_time_float' =>
    double(1492708365.3182)
    'server_port' =>
    int(9999)
    'remote_port' =>
    int(55495)
    'remote_addr' =>
    string(9) "127.0.0.1"
    'server_protocol' =>
    string(8) "HTTP/1.1"
    'server_software' =>
    string(18) "swoole-http-server"
  }
}
  • On Message中的内容
class Swoole\WebSocket\Frame#10 (4) {
  public $fd =>
  int(1)
  public $finish =>
  bool(true)
  public $opcode =>
  int(1)
  public $data =>
  string(4) "asdf"
}
  • 判断用户是否登录
因为TCP/IP模式下, 无法向客户端发送cookie, 所以无法使用session判断用户是否登录.
目前我想到的是, 首先将session存储在redis中, Session存储在redis中是以string形式存储的格式Key以PHPREDIS_SESSION:用户sessionID.
当用户发送连接请求时将用户cookie中的PHPSESSID同时放在消息中发送到SERVER,
Swoole\Websocket\Server通过对用户发送到服务器的消息内容进行处理, 获取到用户PHPSESSID, 
使用该PHPSESSID从redis数据库中查询是否存在, 通过该手段进行判断, 用户是否是登录状态.

  • 发送图片时,怎样通过header判断这是一张图片
暂时未从header头中看到相关信息
仅仅实在On Message中的内容中的$data看到对变量的描述为string

转载于:https://my.oschina.net/chinaliuhan/blog/3063758

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值