亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

PHP用swoole+websocket和redis實(shí)現(xiàn)web一對(duì)一聊天

 更新時(shí)間:2019年11月05日 14:25:12   作者:紅色啤酒罐  
這篇文章主要介紹了PHP用swoole+websocket和redis實(shí)現(xiàn)web一對(duì)一聊天,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

Redis 實(shí)現(xiàn)每個(gè)連接websocket的服務(wù)都唯一綁定一個(gè)用戶。通過(guò) 用戶賬號(hào) = websocket fd 存到redis中。

Mysql 實(shí)現(xiàn)離線消息池。如果一個(gè)用戶不在線,則其他用戶發(fā)送給他的消息暫時(shí)存儲(chǔ)在mysql。待該用戶上線時(shí),再?gòu)碾x線消息池取出發(fā)送。

具體參考代碼和相應(yīng)注釋:

<?php
$server = new swoole_websocket_server("0.0.0.0", 9052);
$redis = new Redis();
$redis->connect('127.0.0.1', 6379);
$db = new mysqli('127.0.0.1', 'test', 'test', 'thinkphp5');

$server->on('open', function (swoole_websocket_server $server, $request) {
 echo "server: handshake success with fd{$request->fd}\n";//$request->fd 是客戶端id
});

$server->on('message', function (swoole_websocket_server $server, $frame) {
 $data = json_decode($frame->data,true); 
 if($data['flag'] == 'init'){
  //用戶剛連接的時(shí)候初始化,每個(gè)用戶登錄時(shí)記錄該用戶對(duì)應(yīng)的fd
  $GLOBALS['redis']->set($data['from'], $frame->fd);
  //處理發(fā)給該用戶的離線消息
  $sql = "SELECT `from`,content FROM thinkphp5.app_offline WHERE `to`='{$data['from']}' AND `from`='{$data['to']}' AND `status`='0' ORDER BY addtime ASC;";
  if ($result = $GLOBALS['db']->query($sql)) {
   $re = array();
   while ($row = $result->fetch_assoc()) {
    array_push($re, $row);
   }
   $result->free();
   foreach($re as $content){
    $content = json_encode($content);
    $server->push($frame->fd , $content);
   }
   //設(shè)置消息池中的消息為已發(fā)送
   $sql = "UPDATE thinkphp5.app_offline SET `status`=1 WHERE `to`='{$data['from']}' AND `from`='{$data['to']}';";
   $GLOBALS['db']->query($sql);
  }
 }else if($data['flag'] == 'msg'){
  //非初始化的信息發(fā)送,一對(duì)一聊天,根據(jù)每個(gè)用戶對(duì)應(yīng)的fd發(fā)給特定用戶
  $tofd = $GLOBALS['redis']->get($data['to']); //消息要發(fā)給誰(shuí)
  $fds = []; //所有在線的用戶(打開聊天窗口的用戶)
  foreach($server->connections as $fd){
   array_push($fds, $fd);
  }
  if(in_array($tofd,$fds)){
   $tmp['from'] = $data['from']; //消息來(lái)自于誰(shuí)
   $tmp['content'] = $data['content']; //消息內(nèi)容
   $re = json_encode($tmp);
   $server->push($tofd , $re);
  }else{
   //該玩家不在線(不在聊天室內(nèi)),將信息發(fā)送到離線消息池
   $time = time();
   $sql = "INSERT INTO thinkphp5.app_offline (`to`,`from`,`content`,`status`,`addtime`) VALUES ('{$data['to']}','{$data['from']}','{$data['content']}','0','{$time}');";
   $GLOBALS['db']->query($sql);
  }
 }else if($data['flag'] == 'group'){
  //todo 群聊
  
 }else if($data['flag'] == 'all'){
  //全站廣播
  foreach($server->connections as $fd){
   $server->push($fd , $data);
  }
 } 
});

$server->on('close', function ($ser, $fd) {
 echo "client {$fd} closed\n";
});

$server->start();

客戶端代碼:

<!DOCTYPE html>
<html>
<head>
 <title>XST-app</title>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
 <meta name="viewport" content="width=device-width, initial-scale=0.0, user-scalable=no, minimum-scale=1.0, maximum-scale=1.0" />
 <meta name="keywords" content="test" />
 <meta name="description" content="test" />
 <meta name="author" content="XST-APP" />
 <meta content="yes" name="apple-mobile-web-app-capable" />
 <meta content="black" name="apple-mobile-web-app-status-bar-style" />
 <meta content="telephone=no" name="format-detection" />
  <style type="text/css">
 body{background:url(/static/images/yuyin_bg.jpg);background-size:100%;}
 @media all and (min-width: 640px) {
  body,html,.wenwen-footer,.speak_window{width:640px!important;margin:0 auto}
  .speak_window,.wenwen-footer{left:50%!important;margin-left:-320px}
 }
 input,button{outline:none;}
 .wenwen-footer{width:100%;position:fixed;bottom:-5px;left:0;background:#fff;padding:3%;border-top:solid 1px #ddd;box-sizing:border-box;}
 .wenwen_btn,.wenwen_help{width:15%;text-align:center;}
 .wenwen_btn img,.wenwen_help img{height:40px;}
 .wenwen_text{height:40px;border-radius:5px;border:solid 1px #636162;box-sizing:border-box;width:66%;text-align:center;overflow:hidden;margin-left:2%;}
 .circle-button{padding:0 5px;}
 .wenwen_text .circle-button{font-size:14px;color:#666;line-height:38px;}
 .write_box{background:#fff;width:100%;height:40px;line-height:40px;}
 .write_box input{height:40px;padding:0 5px;line-height:40px;width:100%;box-sizing:border-box;border:0;}
 .wenwen_help button{width:95%;background:#42929d;color:#fff;border-radius:5px;border:0;height:40px;}
 #wenwen{height:100%;}
 .speak_window{overflow-y:scroll;height:100%;width:100%;position:fixed;top:50px;left:0;}
 .speak_box{margin-bottom:70px;padding:10px;}
 .question,.answer{margin-bottom:1rem;}
 .question{text-align:right;}
 .question>div{display:inline-block;}
 .left{float:left;}
 .right{float:right;}
 .clear{clear:both;}
 .heard_img{height:60px;width:60px;border-radius:5px;overflow:hidden;background:#ddd;}
 .heard_img img{width:100%;height:100%}
 .question_text,.answer_text{box-sizing:border-box;position:relative;display:table-cell;min-height:60px;}
 .question_text{padding-right:20px;}
 .answer_text{padding-left:20px;}
 .question_text p,.answer_text p{border-radius:10px;padding:.5rem;margin:0;font-size:14px;line-height:28px;box-sizing:border-box;vertical-align:middle;display:table-cell;height:30px;word-wrap:break-word;}
 .answer_text p{background:#fff;}
 .question_text p{background:#42929d;color:#fff;text-align:left;}
 .question_text i,.answer_text i{width:0;height:0;border-top:5px solid transparent;border-bottom:5px solid transparent;position:absolute;top:25px;}
 .answer_text i{border-right:10px solid #fff;left:10px;}
 .question_text i{border-left:10px solid #42929d;right:10px;}
 .answer_text p a{color:#42929d;display:inline-block;}
 .write_list{position:absolute;left:0;width:100%;background:#fff;border-top:solid 1px #ddd;padding:5px;line-height:30px;}
  </style>
</head>

<body>
<div id="header" class="head">
  <div class="wrap">
    <i class="menu_back"><a href="javascript:history.go(-1);" rel="external nofollow" ></a></i>
    <div class="title">
      <span class="title_d"><p>與 {$tonickname} 的聊天</p></span>
      <div class="clear"></div>
    </div>
    <!--i class="menu_share"></i-->
  </div>
</div>
<input type="hidden" name="myemail" id="myemail" value="{$myemail}" />
<input type="hidden" name="mynickname" id="mynickname" value="{$mynickname}" />
<input type="hidden" name="myavatar" id="myavatar" value="{$myavatar}" />
<input type="hidden" name="toemail" id="toemail" value="{$toemail}" />
<input type="hidden" name="tonickname" id="tonickname" value="{$tonickname}" />
<input type="hidden" name="toavatar" id="toavatar" value="{$toavatar}" />

<!-- 對(duì)話內(nèi)容 -->
<div class="speak_window">
 <div class="speak_box">

 </div>
</div>
<!-- 內(nèi)容輸入-->
<div class="wenwen-footer">
 <div class="wenwen_btn left"><img src="/static/images/jp_btn.png"></div>
 <div class="wenwen_text left">
  <div class="write_box"><input type="text" class="left" onKeyUp="keyup()" maxlength="100" placeholder="請(qǐng)輸入信息(100字以內(nèi))..." /></div> 
 </div>
 <div class="wenwen_help right">
   <button onClick="send()" class="right">發(fā)送</button>
 </div>
 <div style="opacity:0;" class="clear"></div>
</div>

<script type="text/javascript">
 if ("WebSocket" in window){
  var ws = new WebSocket("ws://192.168.0.1:9052");
  ws.onopen = function(){
   console.log("握手成功");
   var myemail = $("#myemail").val();
   var toemail = $("#toemail").val();
   var arr = {"flag":"init","from":myemail,"to":toemail};
   var str = JSON.stringify(arr);
   ws.send(str);
  };
  ws.onmessage = function(e){
   var toemail = $("#toemail").val();
   var toavatar = $("#toavatar").val();
   var obj = JSON.parse(e.data);
   console.log(e.data);
   //但同時(shí)與兩個(gè)人聊天時(shí),可能兩個(gè)人的消息都會(huì)出現(xiàn)在當(dāng)前窗口,所以此處加個(gè)判斷,此窗口只接收當(dāng)前聊天對(duì)象的消息,其他則忽略
   if(obj.from === toemail){
    var ans = '<div class="answer"><div class="heard_img left"><img src="'+toavatar+'"></div>';
     ans += '<div class="answer_text"><p>'+obj.content+'</p><i></i>';
     ans += '</div></div>';
     $('.speak_box').append(ans);
     for_bottom();
   }
  };
  ws.onerror = function(){
   console.log("error");
   var str = '<div class="question">';
   str += '<div class="heard_img right"><img src="/static/images/xitong.jpg"></div>';
   str += '<div class="question_text clear"><p>聊天服務(wù)器出現(xiàn)異常,暫時(shí)無(wú)法提供服務(wù)。</p><i></i>';
   str += '</div></div>';
   $('.speak_box').append(str);
   $('.write_box input').val('');
   $('.write_box input').focus();
   autoWidth();
   for_bottom();
  };

  function send() {
   var content = $('.write_box input').val();
  if(content === ''){
   alert('請(qǐng)輸入消息!');
   $('.write_box input').focus();
  }else{
    var toemail = $("#toemail").val();
    var myemail = $("#myemail").val();
    var myavatar = $("#myavatar").val();
    var arr = {"flag":"msg","to":toemail,"from":myemail,"content":content};
    var msg = JSON.stringify(arr);
    console.log(msg);
    ws.send(msg); 
    var str = '<div class="question">';
    str += '<div class="heard_img right"><img src="'+myavatar+'"></div>';
    str += '<div class="question_text clear"><p>'+content+'</p><i></i>';
    str += '</div></div>';
   $('.speak_box').append(str);
   $('.write_box input').val('');
   $('.write_box input').focus();
   autoWidth();
   for_bottom();
   }
  
  }
 }else{
  alert("您的瀏覽器不支持 WebSocket!");
 }
   
 function for_bottom(){
 var speak_height = $('.speak_box').height();
 $('.speak_box,.speak_window').animate({scrollTop:speak_height},500);
 }
 
 function autoWidth(){
 $('.question_text').css('max-width',$('.question').width()-60);
 }
 
 autoWidth();
 
</script>

</body>
</html>

數(shù)據(jù)表結(jié)構(gòu):

CREATE TABLE `app_offline` (
 `id` int(11) NOT NULL AUTO_INCREMENT,
 `from` varchar(50) DEFAULT NULL COMMENT '離線發(fā)送方',
 `to` varchar(50) DEFAULT NULL COMMENT '離線接收方',
 `content` varchar(1000) DEFAULT NULL COMMENT '發(fā)送的離線內(nèi)容',
 `status` tinyint(4) DEFAULT '0' COMMENT '發(fā)送狀態(tài):0-未發(fā)送,1-已發(fā)送',
 `addtime` int(11) DEFAULT NULL COMMENT '發(fā)送方發(fā)送時(shí)間',
 PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8

具體效果:


以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • ThinkPHP5.0框架使用build 自動(dòng)生成模塊操作示例

    ThinkPHP5.0框架使用build 自動(dòng)生成模塊操作示例

    這篇文章主要介紹了ThinkPHP5.0框架使用build 自動(dòng)生成模塊操作,結(jié)合實(shí)例形式分析了thinkPHP5使用build自動(dòng)生成模塊的具體步驟、方法與相關(guān)操作注意事項(xiàng),需要的朋友可以參考下
    2019-04-04
  • thinkphp在php7環(huán)境下提示Cannot use ‘String’ as class name as it is reserved的解決方法

    thinkphp在php7環(huán)境下提示Cannot use ‘String’ as class name as it is

    這篇文章主要介紹了thinkphp在php7環(huán)境下提示Cannot use ‘String’ as class name as it is reserved的解決方法,涉及thinkPHP針對(duì)php7關(guān)鍵字判定的相關(guān)底層代碼修改技巧,需要的朋友可以參考下
    2016-09-09
  • PHP中的流(streams)淺析

    PHP中的流(streams)淺析

    這篇文章主要介紹了PHP中的流(streams)淺析,本文講解了流的概述 、流基礎(chǔ)知識(shí)、php://包裝器、流上下文(Stream Contexts)等內(nèi)容,需要的朋友可以參考下
    2015-07-07
  • Yii2中關(guān)聯(lián)查詢簡(jiǎn)單用法示例

    Yii2中關(guān)聯(lián)查詢簡(jiǎn)單用法示例

    這篇文章主要介紹了Yii2中關(guān)聯(lián)查詢簡(jiǎn)單用法,涉及Yii2的數(shù)據(jù)庫(kù)查詢方法及鏈?zhǔn)讲僮骱?jiǎn)單使用技巧,需要的朋友可以參考下
    2016-08-08
  • ThinkPHP框架實(shí)現(xiàn)導(dǎo)出excel數(shù)據(jù)的方法示例【基于PHPExcel】

    ThinkPHP框架實(shí)現(xiàn)導(dǎo)出excel數(shù)據(jù)的方法示例【基于PHPExcel】

    這篇文章主要介紹了ThinkPHP框架實(shí)現(xiàn)導(dǎo)出excel數(shù)據(jù)的方法,結(jié)合實(shí)例形式分析了thinkPHP添加org擴(kuò)展基于PHPExcel進(jìn)行Excel數(shù)據(jù)的導(dǎo)出操作相關(guān)實(shí)現(xiàn)技巧,需要的朋友可以參考下
    2018-05-05
  • php 可變函數(shù)使用小結(jié)

    php 可變函數(shù)使用小結(jié)

    PHP 支持可變函數(shù)的概念。這意味著如果一個(gè)變量名后有圓括號(hào),PHP 將尋找與變量的值同名的函數(shù),并且嘗試執(zhí)行它。本文重點(diǎn)給大家介紹php 可變函數(shù)使用小結(jié),感興趣的朋友一起看看吧
    2018-06-06
  • Zend Framework分發(fā)器用法示例

    Zend Framework分發(fā)器用法示例

    這篇文章主要介紹了Zend Framework分發(fā)器用法,結(jié)合實(shí)例形式分析了Zend Framework分發(fā)器的功能、定義及簡(jiǎn)單使用方法,需要的朋友可以參考下
    2016-12-12
  • laravel 錯(cuò)誤處理,接口錯(cuò)誤返回json代碼

    laravel 錯(cuò)誤處理,接口錯(cuò)誤返回json代碼

    今天小編就為大家分享一篇laravel 錯(cuò)誤處理,接口錯(cuò)誤返回json代碼,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2019-10-10
  • ThinkPHP3.2.2的插件控制器功能簡(jiǎn)述

    ThinkPHP3.2.2的插件控制器功能簡(jiǎn)述

    這篇文章主要介紹了ThinkPHP3.2.2的插件控制器功能,需要的朋友可以參考下
    2014-07-07
  • 老生常談PHP面向?qū)ο笾畼?biāo)識(shí)映射

    老生常談PHP面向?qū)ο笾畼?biāo)識(shí)映射

    下面小編就為大家?guī)?lái)一篇老生常談PHP面向?qū)ο笾畼?biāo)識(shí)映射。小編覺得挺不錯(cuò)的?,F(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06

最新評(píng)論