<?php
$serverIpPort = get_machine_ip();
require 'redis_cli.php';
function getParams($receivedata){
$receivedata = rtrim($receivedata, "\r\n");
$receivedata = rtrim($receivedata, "\n");
$temp = explode("&",$receivedata );
if(!empty($temp)) {
foreach($temp as $value) {
$temp1 = explode("=", $value);
$ret[$temp1[0]] = $temp1[1];
}
}
return $ret;
}
RedisCli::getInstance()->zadd("bb:websocketsys:allsvr",time(),$serverIpPort);
$server = new swoole_websocket_server("0.0.0.0", 9506);
$server->set(array(
'worker_num' => 8,
'daemonize' => false,
'max_request' => 10000,
'dispatch_mode' => 2,
'task_worker_num' => 2,
'debug_mode'=> 0,
));
//定时更新服务器状态 定时删除挂掉的服务器
$server->on('workerStart', function($serv, $worker_id) use ($serverIpPort){
swoole_timer_tick('10000', function() use ($serverIpPort){
RedisCli::getInstance()->zadd("bb:websocketsys:allsvr",time(),$serverIpPort);
RedisCli::getInstance()->zremrangebyscore("bb:websocketsys:allsvr",0,time()-20);//所有ws服务器
});
});
$server->on('open', function (swoole_websocket_server $server, $request) {
writelog("server: handshake success with fd{$request->fd}\n");
});
$server->on('message', function (swoole_websocket_server $server, $frame) use ($serverIpPort){
writelog( "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n");
writelog( "test2\n");
$revdata = json_decode($frame->data,true);
if(!isset($revdata['type'])){
return;
}
if($revdata['type'] == "connect"||$revdata['type'] =="heartbeat" ){//用户连接
$revtype = $revdata['type'];
$userid = $revdata['userid'];//userid
$fd = $frame->fd;
$gid = 0;
if(isset($revdata['gid'])){//如果存在组
$gid = $revdata['gid'];//gid
$currGroupRediskey = "bb:websocketsys:group:$serverIpPort:$gid";
RedisCli::getInstance()->zadd($currGroupRediskey,time(),$fd);//加入到组如果已经在组中进行刷新
RedisCli::getInstance()->zremrangebyscore($currGroupRediskey,0,time()-65);//删除组内已经断线的用户
writelog("get gid:{$gid} type:{$revtype}");
}
$info = "$serverIpPort|$fd";
RedisCli::getInstance()->setex("bb:websocketsys:user:$userid",500,$info);
writelog($revtype.$info);
$fdinfo = $userid;//存储fd对应的用户和组
if($gid){
$fdinfo = "$userid|$gid";
}
RedisCli::getInstance()->setex("bb:websocketsys:fd:$serverIpPort:$fd",500,$fdinfo);
if($revdata['type'] =="heartbeat"){
$server->push($fd,"pang");
}
}
});
$server->on('close', function ($ser, $fd) use ($serverIpPort){
writelog("client {$fd} closed\n");
$t = "bb:websocketsys:fd:$serverIpPort:$fd";
$fdinfo = RedisCli::getInstance()->get("bb:websocketsys:fd:$serverIpPort:$fd");
$fdinfo = explode("|",$fdinfo);
if(count($fdinfo)>1){//组中删除对应的用户
$gid = $fdinfo[1];
RedisCli::getInstance()->zrem("bb:websocketsys:group:$serverIpPort:$gid",$fd);
}
//删除对应的用户
$userid = $fdinfo[0];
RedisCli::getInstance()->del("bb:websocketsys:user:$userid");
RedisCli::getInstance()->del("bb:websocketsys:fd:$serverIpPort:$fd");
});
/**
*群发task
*/
$server->on("Task", function($server, $task_id, $from_id, $data)use ($serverIpPort){
$gid = $data['gid'];//组id
$msg = $data['msg'];//发送的信息
$rediskey = "bb:websocketsys:group:$serverIpPort:$gid";
$maxtime = time()+100;
$mintime = time()-65;
$allfd = RedisCli::getInstance()->zrevrangebyscore($rediskey,$maxtime,$mintime);//获取所有在线的用户
if($allfd){
for($i=0;$i<count($allfd);$i++){
$fd = $allfd[$i];
$server->push($fd,$msg);
}
}
return $gid;
});
/**
*群发task运行完毕
*/
$server->on("Finish", function($serv,$task_id, $data){
writelog("group $data send success\n");
});
$tcpserver = $server->listen("0.0.0.0", 9703, SWOOLE_SOCK_TCP);
$tcpserver->set([
'open_eof_split'=> true,//检测自动分包打开(具体干什么的 我不懂)
'package_eof' => "\n"
]);
$tcpserver->on('Receive', function( swoole_server $serv, $fd, $from_id, $data ) {
writelog("tcp receive");
$params = getParams($data);
$type = $params['type'];
$message = json_decode($params['msg'],true);
if($type=="senduser"){
$userid = $message['userid'];//userid
$wfd = $message['fd'];//fd
$serv->push($wfd, $message['msg']);
}
if($type=="groupsend"){
$gid = $message['gid'];//gid
$taskdata['gid'] = $gid;
$taskdata['msg'] = $message['msg'];
$serv->task($taskdata);
}
$serv->close($fd);//一定要主动释放
});
$tcpserver->on('connect', function($serv, $fd){
});
$tcpserver->on('close', function($serv, $fd){
});
//启动连接
$server->start();
function get_machine_ip()
{
$myip = httpRequest("http://bangbang.ied.tencent-cloud.net/app/dnf/yuanxiaowishact/getuserip");
return $myip[2];
}
/**
* 获取指定url内容
* @param string $url url
* @param array $params 参数
* @param array $method post/get
* @return int
*/
function httpRequest( $url,$params=false,$method='get',$reffer='' ,$header=array('Expect:'),$timeout = 5,$contime=3) {
$options = array(
CURLOPT_RETURNTRANSFER => true,
CURLOPT_TIMEOUT => $timeout,
CURLOPT_CONNECTTIMEOUT=> $contime,
CURLOPT_FOLLOWLOCATION => 1,
CURLOPT_BINARYTRANSFER => true,
CURLOPT_URL => $url,
CURLOPT_SSL_VERIFYPEER => false,
CURLOPT_SSL_VERIFYHOST => false,
CURLOPT_HEADER => false,
CURLOPT_HTTPHEADER => $header,
CURLOPT_REFERER => $reffer
);
if($method === 'post') {
$query_string = array();
if(is_array($params)) {
foreach ($params as $key => $value) {
array_push($query_string, rawurlencode($key) . '=' . rawurlencode($value));
}
$params = join('&', $query_string);
}
$options[CURLOPT_POST] = 1;
$options[CURLOPT_POSTFIELDS] = $params;
} else {
$options[CURLOPT_POST] = 0;
}
$ch = curl_init($url);
curl_setopt_array($ch,$options);
$result = curl_exec($ch);
$errno = curl_errno($ch);
$errmsg = curl_error($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
return array($errno, $httpCode, $result);
}
function writelog($str){
echo $str."\n";
}
05-24
05-24
04-18
08-28