在直播室源碼中,直播間人數是關鍵的統計數據,由於需要統計實時的人數,因此需要如下處理。
1.當用戶進入和退出直播間,觸發進入和退出直播間的廣播,通知客戶端增減人數。
2.當新用戶進入直播間時,要給該用戶提供相應的房間人數的數據
3.在數據庫中存儲累計人數,用於統計
4.Redis中存儲用戶列表,方便用戶列表的相關功能使用
處理代碼如下:
1.進入房間部分
//進入房間
socket.on(‘conn’, function(data) {
if(!data || !data.token){
return !1;
}
userid=data.uid;
old_socket = sockets[userid];
if (old_socket && old_socket != socket) {
if(data.uid != data.roomnum && data.uid==old_socket.roomnum){
/* 進房間 但舊鏈接是 主播 */
var data_str='{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播關閉"}]}';
old_socket.emit('broadcastingListen',[data_str]);
}else if(data.uid== data.roomnum && data.stream==old_socket.stream){
/* 主播重連 */
old_socket.reusing = 1;
//console.log("重用");
}else if(data.uid== data.roomnum && data.stream!=old_socket.stream){
/* 主播多端開播 */
var data_str='{"retmsg":"ok","retcode":"000000","msg":[{"msgtype":"1","_method_":"StartEndLive","action":"19","ct":"直播關閉"}]}';
old_socket.emit('broadcastingListen',[data_str]);
}
old_socket.disconnect()
}
clientRedis.get(data.token,function(error,res){
if(error){
return;
}else if(res==null){
//console.log("[獲取token失敗]"+data.uid);
}else{
if(res != null){
var userInfo = evalJson(res);
if(userInfo['id'] == data.uid ){
//console.log("[初始化驗證成功]--"+data.uid+"---"+data.roomnum+'---'+data.stream);
//獲取驗證token
socket.token = data.token;
socket.roomnum = data.roomnum;
socket.stream = data.stream;
socket.nicename = userInfo['user_nicename'];
socket.level = userInfo['level'];
socket.avatar = userInfo['avatar'];
socket.sign = Number(userInfo['sign']);
socket.usertype = parseInt(userInfo['usertype']);
socket.uid = data.uid;
socket.reusing = 0;
socket.join(data.roomnum);
sockets[userid] = socket;
socket.emit('conn',['ok']);
if( socket.roomnum!=socket.uid && socket.uid >0 ){
/* 處理有時 無座駕信息會崩潰的問題 */
var car_id='0';
var car_swf='';
var car_swftime='';
var car_words='';
if(userInfo.hasOwnProperty("car")){
var carinfo=userInfo['car'];
if(carinfo.hasOwnProperty("id")){
car_id=carinfo['id'];
}
if(carinfo.hasOwnProperty("swf")){
car_swf=carinfo['swf'];
}
if(carinfo.hasOwnProperty("swftime")){
car_swftime=carinfo['swftime'];
}
if(carinfo.hasOwnProperty("words")){
car_words=carinfo['words'];
}
}
var data_obj={
"msg":[
{
"_method_":"SendMsg",
"action":"0",
"ct":{
"id":''+userInfo['id'],
"user_nicename":''+userInfo['user_nicename'],
"avatar":userInfo['avatar'],
"avatar_thumb":userInfo['avatar_thumb'],
"level":''+userInfo['level'],
"usertype":''+userInfo['usertype'],
"vip_type":''+userInfo['vip']['type'],
"guard_type":''+userInfo['guard_type'],
"liangname":''+userInfo['liang']['name'],
"car_id":''+car_id,
"car_swf":''+car_swf,
"car_swftime":''+car_swftime,
"car_words":''+car_words
},
"msgtype":"0"
}
],
"retcode":"000000",
"retmsg":"OK"
};
//發送進入房間消息
process_msg(io,socket.roomnum,JSON.stringify(data_obj));
if(socket.stream){
clientRedis.zadd('user_'+socket.stream,socket.sign,userInfo['id']);
}
}
sendSystemMsg(socket,"直播內容包含任何低俗、暴露和涉黃內容,賬號會被封禁;安全部門會24小時巡查哦~");
return;
}else{
socket.disconnect();
}
}
}
socket.emit('conn',['no']);
});
});
2.離開房間部分
//資源釋放
socket.on('disconnect', function() {
/* numscount--;
if(numscount<0){
numscount=0;
} */
if(socket.roomnum ==null || socket.token==null || socket.uid <=0){
return !1;
}
d.run(function() {
/* 用戶連麥 */
clientRedis.hget('ShowVideo',socket.roomnum,function(error,res){
if(error){
return !1;
}
if(!res){
return !1;
}
var res_j=JSON.parse(res);
if( socket.uid == res_j['uid'] || socket.uid == socket.roomnum ){
clientRedis.hdel('ShowVideo',socket.roomnum);
var data_obj={
"msg":[
{
"_method_":"ConnectVideo",
"action":"5",
"msgtype":"10",
"uid":""+socket.uid,
"uname":""+socket.nicename
}
],
"retcode":"000000",
"retmsg":"OK"
};
process_msg(io,socket.roomnum,JSON.stringify(data_obj));
}
});
if(socket.roomnum==socket.uid){
/* 主播 */
if(socket.reusing==0){
request(config['WEBADDRESS']+"?service=Live.stopRoom&uid="+socket.uid + "&token=" + socket.token+ "&type=1&stream=" + socket.stream,function(error, response, body){
var data_obj={
"retmsg":"ok",
"retcode":"000000",
"msg":[
{
"msgtype":"1",
"_method_":"StartEndLive",
"action":"18",
"ct":"直播關閉"
}
]
};
process_msg(io,socket.roomnum,JSON.stringify(data_obj));
// console.log('關播');
// console.log(FormatNowDate());
// console.log('uid---'+socket.uid);
});
endLiveConnect(io,socket.uid);
}
}else{
/* 觀衆 */
clientRedis.zrem('user_'+socket.stream,socket.uid,function(error,res){
if(error) return;
if(res){
var data_obj={
"msg":[
{
"_method_":"disconnect",
"action":"1",
"ct":{
"id":''+socket.uid,
"user_nicename":''+socket.nicename,
"avatar":socket.avatar,
"level":''+socket.level
},
"msgtype":"0",
"uid":''+socket.uid,
"uname":socket.nicename
}
],
"retcode":"000000",
"retmsg":"OK"
};
process_msg(io,socket.roomnum,JSON.stringify(data_obj));
}
});
}
////console.log(socket.roomnum+"==="+socket.token+"===="+socket.uid+"======"+socket.stream);
socket.leave(socket.roomnum);
delete io.sockets.sockets[socket.id];
sockets[socket.uid] = null;
delete sockets[socket.uid];
});
});
});
3.用戶進入房間返回數據與緩存操作
public function enterRoom() {
$rs = array(‘code’ => 0, ‘msg’ => ‘’, ‘info’ => array());
$uid=$this->uid;
$token=checkNull($this->token);
$liveuid=$this->liveuid;
$city=checkNull($this->city);
$stream=checkNull($this->stream);
$checkToken=checkToken($uid,$token);
if($checkToken==700){
$rs['code'] = $checkToken;
$rs['msg'] = '您的登陸狀態失效,請重新登陸!';
return $rs;
}
$isban = isBan($uid);
if(!$isban){
$rs['code']=1001;
$rs['msg']='該賬號已被禁用';
return $rs;
}
$domain = new Domain_Live();
$domain->checkShut($uid,$liveuid);
$userinfo=getUserInfo($uid);
$carinfo=getUserCar($uid);
$userinfo['car']=$carinfo;
$issuper='0';
if($userinfo['issuper']==1){
$issuper='1';
DI()->redis -> hset('super',$userinfo['id'],'1');
}else{
DI()->redis -> hDel('super',$userinfo['id']);
}
if(!$city){
$city='好像在火星';
}
$data=array('city'=>$city);
$domain2 = new Domain_User();
$info = $domain2->userUpdate($uid,$data);
$userinfo['city']=$city;
$usertype = isAdmin($uid,$liveuid);
$userinfo['usertype'] = $usertype;
$stream2=explode('_',$stream);
$showid=$stream2[1];
$contribution='0';
if($showid){
$contribution=$domain->getContribut($uid,$liveuid,$showid);
}
$userinfo['contribution'] = $contribution;
unset($userinfo['issuper']);
/* 守護 */
$domain_guard = new Domain_Guard();
$guard_info=$domain_guard->getUserGuard($uid,$liveuid);
$guard_nums=$domain_guard->getGuardNums($liveuid);
$userinfo['guard_type']=$guard_info['type'];
/* 等級+100 保證等級位置位數相同,最後拼接1 防止末尾出現0 */
$userinfo['sign']=$userinfo['contribution'].'.'.($userinfo['level']+100).'1';
DI()->redis -> set($token,json_encode($userinfo));
/* 用戶列表 */
$userlists=$this->getUserList($liveuid,$stream);
/* 用戶連麥 */
$linkmic_uid='0';
$linkmic_pull='';
$showVideo=DI()->redis -> hGet('ShowVideo',$liveuid);
// file_put_contents('./showVideo.txt',date('Y-m-d H:i:s').' 提交參數信息 liveuid:'.json_encode($liveuid)."\r\n",FILE_APPEND);
// file_put_contents('./showVideo.txt',date('Y-m-d H:i:s').' 提交參數信息 showVideo:'.json_encode($showVideo)."\r\n",FILE_APPEND);
if($showVideo){
$showVideo_a=json_decode($showVideo,true);
$linkmic_uid=$showVideo_a['uid'];
$linkmic_pull=$this->getPullWithSign($showVideo_a['pull_url']);
}
/* 主播連麥 */
$pkinfo=array(
'pkuid'=>'0',
'pkpull'=>'0',
'ifpk'=>'0',
'pk_time'=>'0',
'pk_gift_liveuid'=>'0',
'pk_gift_pkuid'=>'0',
);
$pkuid=DI()->redis -> hGet('LiveConnect',$liveuid);
//file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交參數信息 進房間:'."\r\n",FILE_APPEND);
//file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交參數信息 uid:'.json_encode($uid)."\r\n",FILE_APPEND);
//file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交參數信息 liveuid:'.json_encode($liveuid)."\r\n",FILE_APPEND);
if($pkuid){
$pkinfo['pkuid']=$pkuid;
/* 在連麥 */
$pkpull=DI()->redis -> hGet('LiveConnect_pull',$pkuid);
$pkinfo['pkpull']=$this->getPullWithSign($pkpull);
$ifpk=DI()->redis -> hGet('LivePK',$liveuid);
if($ifpk){
$pkinfo['ifpk']='1';
$pk_time=DI()->redis -> hGet('LivePK_timer',$liveuid);
if(!$pk_time){
$pk_time=DI()->redis -> hGet('LivePK_timer',$pkuid);
}
$nowtime=time();
if($pk_time && $pk_time >0 && $pk_time< $nowtime){
$cha=5*60 - ($nowtime - $pk_time);
$pkinfo['pk_time']=(string)$cha;
$pk_gift_liveuid=DI()->redis -> hGet('LivePK_gift',$liveuid);
if($pk_gift_liveuid){
$pkinfo['pk_gift_liveuid']=(string)$pk_gift_liveuid;
}
$pk_gift_pkuid=DI()->redis -> hGet('LivePK_gift',$pkuid);
if($pk_gift_pkuid){
$pkinfo['pk_gift_pkuid']=(string)$pk_gift_pkuid;
}
}else{
$pkinfo['ifpk']='0';
}
}
}
//file_put_contents('./LiveConnect.txt',date('Y-m-d H:i:s').' 提交參數信息 pkinfo:'.json_encode($pkinfo)."\r\n",FILE_APPEND);
$configpri=getConfigPri();
$info=array(
'votestotal'=>$userlists['votestotal'],
'barrage_fee'=>$configpri['barrage_fee'],
'userlist_time'=>$configpri['userlist_time'],
'chatserver'=>$configpri['chatserver'],
'linkmic_uid'=>$linkmic_uid,
'linkmic_pull'=>$linkmic_pull,
'nums'=>$userlists['nums'],
'speak_limit'=>$configpri['speak_limit'],
'barrage_limit'=>$configpri['barrage_limit'],
'coin'=>$userinfo['coin'],
'vip'=>$userinfo['vip'],
'liang'=>$userinfo['liang'],
'issuper'=>(string)$issuper,
'usertype'=>(string)$usertype,
);
$info['isattention']=(string)isAttention($uid,$liveuid);
$info['userlists']=$userlists['userlist'];
/* 守護 */
$info['guard']=$guard_info;
$info['guard_nums']=$guard_nums;
/* 主播連麥/PK */
$info['pkinfo']=$pkinfo;
/* 紅包 */
$key='red_list_'.$stream;
$nums=DI()->redis->lSize($key);
$isred='0';
if($nums>0){
$isred='1';
}
$info['isred']=$isred;
/* 獎池 */
$info['jackpot_level']='-1';
$jackpotset = getJackpotSet();
if($jackpotset['switch']){
$jackpotinfo = getJackpotInfo();
$info['jackpot_level']=$jackpotinfo['level'];
}
$rs['info'][0]=$info;
return $rs;
}