English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

php+Exemple de code pour la salle de chat réalisée avec webSoket (avec le code source)

Récemment, en utilisant la salle de直播 pour construire une salle de chat graphique dans l'entreprise, j'ai besoin de chatsever, j'ai étudié un peu l'html5Le websocket a réalisé la communication bidirectionnelle sur le site web, selon l'expérience des anciens, j'ai joué avec pendant quelques jours et j'ai réalisé un salon de chat, permettant l'envoi d'images, l'envoi d'émoticônes QQ, la conversation de groupe et privée, etc., je le partage spécialement avec les débutants pour la référence et l'apprentissage, les experts peuvent ignorer.

前端:client.html

!doctype html
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no"/>
<title>HTML5 websocket 网页聊天室 javascript php</title>
<style type="text/css">
body,p{margin:0px; padding:0px; font-size:14px; color:#333; font-family:Arial, Helvetica, sans-serif;}
#ltian,.rin{width:98%; margin:5px auto;}
#ltian{border:1px #ccc solid;overflow-y:auto; overflow-x:hidden; position:relative;}
#ct{margin-right:111px; height:100%;overflow-y:auto;overflow-x: hidden;}
#us{width:110px; overflow-y:auto; overflow-x:hidden; float:right; border-left:1px #ccc solid; height:100%; background-color:#F1F1F1;}
#us p{padding:3px 5px; color:#08C; line-height:20px; height:20px; cursor:pointer; overflow:hidden; white-space:nowrap; text-overflow:ellipsis;}
#us p:hover,#us p:active,#us p.ck{background-color:#069; color:#FFF;}
#us p.my:hover,#us p.my:active,#us p.my{color:#333;background-color:transparent;}
button{float:right; width:80px; height:35px; font-size:18px;}
input{width:100%; height:30px; padding:2px; line-height:20px; outline:none; border:solid 1px #CCC;}
.rin p{margin-right:160px;}
.rin span{float:right; padding:6px 5px 0px 5px; position:relative;}
.rin span img{margin:0px 3px; cursor:pointer;}
.rin span form{position:absolute; width:25px; height:25px; overflow:hidden; opacity:0; top:5px; right:5px;}
.rin span input{width:180px; height:25px; margin-left:-160px; cursor:pointer}
#ct p{padding:5px; line-height:20px;}
#ct a{color:#069; cursor:pointer;}
#ct span{color:#999; margin-right:10px;}
.c2{color:#999;}
.c3{background-color:#DBE9EC; padding:5px;}
.qp{position:absolute; font-size:12px; color:#666; top:5px; right:130px; text-decoration:none; color:#069;}
#ems{position:absolute; z-index:5; display:none; top:0px; left:0px; max-width:230px; background-color:#F1F1F1; border:solid 1px #CCC; padding:5px;}
#ems img{width:44px; height:44px; border:solid 1px #FFF; cursor:pointer;}
#ems img:hover,#ems img:active{border-color:#A4",true));7DA3;}
#ems a{color:#069; border-radius:2px; display:inline-block; margin:2px 5px; padding:1px 8px; text-decoration:none; background-color:#D5DFFD;}
#ems a:hover,#ems a:active,#ems a.ck{color:#FFF; background-color:#069;}
.tc{text-align:center; margin-top:5px;}
</style>
</head>
<body>
<div id="ltian">
 <div id="us" class="jb"></div>
 <div id="ct"></div>
 <a href="javascript:;" rel="external nofollow" rel="external nofollow" class="qp" onClick="this.parentNode.children[1].innerHTML=''">effacer</a>
</div>
<div class="rin">
 <button id="sd">envoyer</button>
 <span><img src="http://www.yxsss.com/ui/sk/t.png" title="[#1#]" id="imgbq"><img src="http://www.yxsss.com/ui/sk/e.png" title="[#2#]"><form><input type="file" title="[#2#]" id="upimg"></form></span>
 <p><input id="nrong"></p>
</div>
<div id="ems"><p></p><p class="tc"></p></div>
<script>
if(typeof(WebSocket)=='undefined'){
 alert('你的浏览器不支持 WebSocket ,推荐使用Google Chrome 或者 Mozilla Firefox'); 
}
</script>
<script src="http://www.yxsss.com/ui/p/a.js" type="text/javascript"></script>
<script>
(function(){
 var key='all',mkey;
 var users={};
 var url='ws://127.0.0.1:8000';
 var so=false,n=false;
 var lus=A.$('us'),lct=A.$('ct');
 function st(){
  var Arr1 = ["聪明的","狡猾的","可爱的","美丽的","狡猾的","善良的","帅气的","逗比的"]; 
  var Arr2 = ["大灰狼","小白兔","母老虎","外星人","皮卡丘","HelloKitty","吴亦凡","薛之谦"]; 
  var ran1 = Math.floor(Math.random() * Arr1.length + 1>-1; 
  var ran2 = Math.floor(Math.random() * Arr2.length + 1>-1; 
  var n=Arr1[ran1]+Arr2[ran2]; 
  //以上五行是用来随机生成用户昵称的方法,参考一下 ,如果想自定义用户名可以将以上五行注释,然后以下两行取消注释
  //n=prompt('请给自己取一个霸气的名字:');
  //n=n.substr(0,16]);
  //console.log(n);
  if(!n){
   return ; 
  }
  so=new WebSocket(url);
  so.onopen=function(){
   if(so.readyState==1{
    so.send('type=add&ming='+n);
   }
  }
  so.onclose=function(){
   so=false;
   lct.appendChild(A.$$('<p class="c',2">退出聊天室</p>'));
  }
  so.onmessage=function(msg){
   eval('var da='+msg.data);
   var obj=false,c=false;
   if(da.type=='add'){
    var obj=A.$$('<p>'+da.name+'</p)>;
    lus.appendChild(obj);
    cuser(obj,da.code);
    obj=A.$$('<p><span>['+da.time+']</span>欢迎<a>'+da.name+'</a>加入</p)>;
    c=da.code;
   }else if(da.type=='madd'){
    mkey=da.code;
    da.users.unshift({'code':'all','name':'大家'});
    for(var i=0;i<da.users.length;i++{
     var obj=A.$$('<p>'+da.users[i].name+'</p)>;
     lus.appendChild(obj);
     if(mkey!=da.users[i].code){
      cuser(obj,da.users[i].code);
     }else{
      obj.className='my';
      document.title=da.users[i].name;
     }
    }
    obj=A.$$('<p><span>['+da.time+']</span>欢迎'+da.name+'加入</p)>;
    users.all.className='ck';
   }
   if(obj==false){
    if(da.type=='rmove'){
     var obj=A.$$('<p class="c2><span>['+da.time+']</span>'+users[da.nrong].innerHTML+'退出聊天室</p)>;
     lct.appendChild(obj);
     users[da.nrong].del();
     delete users[da.nrong];
    }else{
     da.nrong=da.nrong.replace(/{\\(\d+})/g,function(a,b){
      return '<img src="sk/'+b+'.jpg">';
     }).replace(/^data\:image\/png;base64\,.{50,}$/i,function(a){
      return '<img src="'+a+'">';
     });
     //da.code 发信息人的code
     if(da.code1==mkey){
      obj=A.$$('<p class="c3><span>['+da.time+']</span><a>'+users[da.code].innerHTML+'</a>对我说:'+da.nrong+'</p)>;
      c=da.code;
     }else if(da.code==mkey){
      if(da.code1!='all')
      obj=A.$$('<p class="c3><span>['+da.time+']</span>我对<a>'+users[da.code1].innerHTML+'</a>说:'+da.nrong+'</p)>;
      else
      obj=A.$$('<p><span>['+da.time+']</span>我对<a>'+users[da.code1].innerHTML+'</a>说:'+da.nrong+'</p)>;
      c=da.code1;
     }else if(da.code==false){
      obj=A.$$('<p><span>['+da.time+']</span>'+da.nrong+'</p)>;
     }else if(da.code1{
      obj=A.$$('<p><span>['+da.time+']</span><a>'+users[da.code].innerHTML+'</a>对'+users[da.code1].innerHTML+':'+da.nrong+'</p)>;
      c=da.code;
     }
    }
   }
   if(c){
     obj.children[1].onclick=function(){
      users[c].onclick();
     }
    }
   lct.appendChild(obj);
   lct.scrollTop=Math.max(0,lct.scrollHeight-lct.offsetHeight);
  }
 }
 A.$('sd').onclick=function(){
  si(!so){
    return st();
  }
  var da=A.$('nrong').value.trim();
  if(da==''){
   alert('内容不能为空');
   return false; 
  }
  A.$('nrong').value='';
  so.send('nr='+esc(da)+'&key='+key);
 }
 A.$('nrong').onkeydown=function(e){
  var e=e||event;
  if(e.keyCode==13{
   A.$('sd').onclick();
  }
 }
 function esc(da){
  da=da.replace(/</g,'<').replace(/>/g,'>').replace(/\"/g,'"');
  return encodeURIComponent(da);
 }
 function cuser(t,code){
  users[code]=t;
  t.onclick=function(){
   t.parentNode.children.rcss('ck','');
   t.rcss('','ck');
   key=code;
  }
 }
 A.$('ltian').style.height=(document.documentElement.clientHeight - 70);+"px";
 st();
 var bq=A.$('imgbq'),ems=A.$('ems');
 var l=80,r=4,c=5,s=0,p=Math.ceil(l/(r*c));
 var pt='sk/';
 bq.onclick=function(e){
  var e=e||event;
  si(!so){
    return st();
  }
  ems.style.display='block';
  document.onclick=function(){
   gb(); 
  }
  ct();
  try{e.stopPropagation();}catch(o){}
 }
 for(var i=0;i<p;i++{
  var a=A.$('<a href="javascript:;" rel="external nofollow" rel="external nofollow" >'+(i+1>+'</a)>;
  ems.children[1.appendChild(a);
  ef(a,i);
 }
 ems.children[1].children[0].className='ck';
 function ct(){
  var wz=bq.weiz();
  with(ems.style){
   top=wz.y-242+"px";
   left=wz.x+bq.offsetWidth-235+"px";
  }
 }
 function ef(t,i){
  t.onclick=function(e){
   var e=e||event;
   s=i*r*c;
   ems.children[0].innerHTML='';
   hh();
   this.parentNode.children.rcss('ck','');
   this.rcss('','ck');
   try{e.stopPropagation();}catch(o){}
  }
 }
 function hh(){
  var z=Math.min(l,s+r*c);
  pour(var i=s;i<z;i++{
   var a=A.$$('<img src="'+pt+i+'.jpg">');
   hh1(a,i);
   ems.children[0].appendChild(a);
  }
  ct();
 }
 function hh1(t,i){
  t.onclick=function(e){
   var e=e||event;
   A.$('nrong').value+='{\\'+i+};
   si(!e.ctrlKey){
    gb();
   }
   try{e.stopPropagation();}catch(o){}
  }
 }
 function gb(){
  ems.style.display='';
  A.$('nrong').focus();
  document.onclick='';
 }
 hh();
 A.on(window,'resize',function(){
  A.$('ltian').style.height=(document.documentElement.clientHeight - 70);+"px";
  ct();
 }); 
 var fimg=A.$('upimg');
 var img=new Image();
 var dw=400,dh=300;
 A.on(fimg,'change',function(ev){
  si(!so){
   st();
   return false;
  }
  si(key=='all'){
   alert('En raison des limitations des ressources, l'envoi d'images n'est possible que par message privé');
   return false; 
  }
  var f=ev.target.files[0];
  si(f.type.match('image.', "*')){}}
   var r = new FileReader();
   r.onload = function(e){
    img.setAttribute('src',e.target.result);
   };
   r.readAsDataURL(f);
  }
 });
 img.onload=function(){
  ih=img.height,iw=img.width;
  if(iw/ih > dw/dh && iw > dw){
   ih=ih/iw*dw;
   iw=dw;
  }else if(ih > dh){
   iw=iw/ih*dh;
   ih=dh;
  }
  var rc = A.$$('canvas');
  var ct = rc.getContext('2d');
  rc.width=iw;
  rc.height=ih;
  ct.drawImage(img,0,0,iw,ih);
  var da=rc.toDataURL();
  so.send('nr='+esc(da)+'&key='+key);
 }
})();
</script>
</body>
</html>

code arrière : webserver.php

<?php
error_reporting(E_ALL ^ E_NOTICE);
ob_implicit_flush();
$sk=new Sock('127.0.0.1',8000);
$sk->run();
class Sock{
 public $sockets;
 public $users;
 public $master;
 private $sda=array();//données reçues
 private $slen=array();//longueur totale des données
 private $sjen=array();//longueur de données reçues
 private $ar=array();//clé de chiffrement
 private $n=array();
 public function __construct($address, $port){
 $this->master=$this->WebSocket($address, $port);
 $this->sockets=array($this->master);
 }
 function run(){
 while(true){
 $changes=$this->sockets;
 $write=NULL;
 $except=NULL;
 socket_select($changes,$write,$except,NULL);
 foreach($changes as $sock){
 if($sock==$this->master){
  $client=socket_accept($this->master);
  $key=uniqid();
  $this->sockets[]=$client;
  $this->users[$key]=array(
  'socket'=>$client,
  'shou'=>false
  ]);
 }else{
  $len=0;
  $buffer='';
  do{
  $l=socket_recv($sock,$buf,1000,0);
  $len+=$l;
  while($l==
  }1000);
  $k=$this->search($sock);
  if($len<7{
  $this->send2($k);
  continue;
  }
  if(!$this->users[$k]['shou']){
  $this->woshou($k,$buffer);
  }else{
  $buffer = $this->uncode($buffer,$k);
  if($buffer==false){
  continue;
  }
  $this->send($k,$buffer);
  }
 }
 }
 }
 }
 function close($k){
 socket_close($this->users[$k]['socket']);
 unset($this->users[$k]);
 $this->sockets=array($this->master);
 foreach($this->users as $v){
 $this->sockets[]=$v['socket'];
 }
 $this->e("key:$k close");
 }
 function search($sock){
 foreach ($this->users as $k=>$v){
 if($sock==$v['socket'])
 return $k;
 }
 return false;
 }
 function WebSocket($address,$port){
 $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
 socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1]);
 socket_bind($server, $address, $port);
 >e('Server Started : '.date('Y
 $this-m-d H:i:s'));->e('Listening on : '.$address.' port '.$port);
 $this-return $server;
 function woshou($k,$buffer){
 }
 $buf = substr($buffer,strpos($buffer,'Sec
 Key:')-Accept: " . $new_key . "\r\n\r\n";-$key = trim(substr($buf,0,strpos($buf,"\r\n")));+18]);
 $new_key = base
 _encode(sha64($key."1EAFA258E5-DA914-47CA-95AB0DC-C5B85",true));11$new_message = "HTTP
 Switching Protocols\r\n";/1.1 101 $new_message .= "Upgrade: websocket\r\n";
 Version:
 WebSocket-Accept: " . $new_key . "\r\n\r\n";-\r\n"; 13$new_message .= "Connection: Upgrade\r\n";
 $new_message .= "Sec
 WebSocket-Accept: " . $new_key . "\r\n\r\n";->users[$k]['socket'],$new_message,strlen($new_message));
 socket_write($this->users[$k]['shou']=true;
 $this-return true;
 function uncode($str,$key){
 }
 $mask = array();
 $data = ''; 
 $msg = unpack('H 
 ',$str);*$head = substr($msg[
 ],0,1if ($head == '2]); 
 ' && !isset($this81>slen[$key])) {-if(substr($msg[ 
 $len=substr($msg[1,2$s =2]);
 $len=hexdec($len);
 ])=='fe'){1,2$s =2else if(substr($msg[
 $len=substr($msg[1,4$s =4]);
 $len=hexdec($len);
 $msg[1]=substr($msg[1,4]);
 }1,2$s =2])=='ff'){
 $len=substr($msg[1,4$s =16]);
 $len=hexdec($len);
 $msg[1]=substr($msg[1,16]);
 }
 $mask[] = hexdec(substr($msg[1,4$s =2)); 
 $mask[] = hexdec(substr($msg[1,6$s =2)); 
 $mask[] = hexdec(substr($msg[1,8$s =2)); 
 $mask[] = hexdec(substr($msg[1,10$s =2));
 $n=0; 12;
 else if($this
 }->slen[$key] > 0){
 $len=$this->slen[$key];
 $mask=$this->ar[$key];
 $n=$this->n[$key];
 $s = 0;
 }
 $e = strlen($msg[1)-2;
 for ($i=$s; $i<= $e; $i+= 2) { 
 $data .= chr($mask[$n%4]^hexdec(substr($msg[1],$i,2); 
 $n++; 
 } 
 $dlen=strlen($data);
 if($len > 255 && $len > $dlen+intval($this->sjen[$key])){
 $this->ar[$key]=$mask;
 $this->slen[$key]=$len;
 $this->sjen[$key]=$dlen+intval($this->sjen[$key]);
 $this->sda[$key]=$this->sda[$key].$data;
 $this->n[$key]=$n;
 return false;
 }else{
 unset($this->ar[$key],$this->slen[$key],$this->sjen[$key],$this->n[$key]);
 $data=$this->sda[$key].$data;
 unset($this->sda[$key]);
 return $data;
 }
 }
 function code($msg){
 $frame = array(); 
 $frame[0] = '81'; 
 $len = strlen($msg);
 if($len < 126{
 $frame[1] = $len<16?'0'.dechex($len):dechex($len);
 }else if($len < 65025{
 $s=dechex($len);
 $frame[1]='7e'.str_repeat('0',4-strlen($s)).$s;
 }else{
 $s=dechex($len);
 $frame[1]='7f'.str_repeat('0',16-strlen($s)).$s;
 }
 $frame[2] = $this->ord_hex($msg); 
 $data = implode('',$frame); 
 return pack("H"*", $data); 
 }
 function ord_hex($data) { 
 $msg = ''; 
 $l = strlen($data); 
 for ($i= 0; $i<$l; $i++) { 
 $msg .= dechex(ord($data{$i})); 
 } 
 return $msg; 
 }
 //Utilisateur ajouté
 function send($k,$msg){
 parse_str($msg,$g);
 $ar=array();
 if($g['type']=='add'){
 $this->users[$k]['name']=$g['ming'];
 $ar['type']='add';
 $ar['name']=$g['ming'];
 $key='all';
 }else{
 $ar['nrong']=$g['nr'];
 $key=$g['key'];
 }
 $this->send1($k,$ar,$key);
 }
 function getusers(){
 $ar=array();
 foreach($this->users as $k=>$v){
 $ar[]=array('code'=>$k,'name'=>$v['name']);
 }
 return $ar;
 }
 //$k 发信息人的code $key接受人的 code
 function send1($k,$ar,$key='all'){
 $ar['code1]=$key;
 $ar['code']=$k;
 $ar['time']=date('m-d H:i:s');
 $str = $this->code(json_encode($ar));
 if($key=='all'){
 $users=$this->users;
 if($ar['type']=='add'){
 $ar['type']='madd';
 $ar['users']=$this->getusers();
 $str1 = $this->code(json_encode($ar));
 socket_write($users[$k]['socket'],$str1,strlen($str1));
 unset($users[$k]);
 }
 foreach($users as $v){
 socket_write($v['socket'],$str,strlen($str));
 }
 }else{
 socket_write($this->users[$k]['socket'],$str,strlen($str));
 socket_write($this->users[$key]['socket'],$str,strlen($str));
 }
 }
 //L'utilisateur se déconnecte
 function send2($k){
 $this->close($k);
 $ar['type']='rmove';
 $ar['nrong']=$k;
 $this->send1(false,$ar,'all');
 }
 function e($str){
 //$path=dirname(__FILE__).'/log.txt';
 
 //error_log($str,3$path);
 echo iconv('utf-8','gbk//IGNORE,$str);
 }
}
?>

Beaucoup d'élèves ont signalé que mon projet de code source ne fonctionne pas, qu'il y a des erreurs, et qu'il ne peut pas être exécuté. Voici les étapes d'installation et de déploiement détaillées.

Tout d'abord, décompressez le code source téléchargé et placez-le dans le répertoire web, par exemple, le mien est applications/Xampp/xamppfiles/htdocs/phpb/websocket,

Chemin

Ensuite, utilisez l'outil en ligne de commande pour vous déplacer dans ce répertoire et exécuter la commande :

php websocket.php

Effet visuel de l'exécution :

Opérations en ligne de commande

Ensuite, ouvrez le serveur Apache, accédez à http: dans le navigateur//localhost/phpb/websocket/client.html

Effet visuel de l'exécution :

Lien de code source :webSoket-php-chatsever_jb51.rar

Voici la totalité du contenu de cet article, j'espère qu'il vous sera utile dans vos études, et j'espère que vous soutiendrez également le tutoriel à crier.

Déclaration : le contenu de cet article est issu d'Internet, propriété des auteurs respectifs, contribué et téléversé par les utilisateurs d'Internet. Ce site n'a pas de propriété, n'a pas été édité par l'homme et n'assume aucune responsabilité juridique. Si vous trouvez du contenu suspect de violation de droits d'auteur, vous êtes invité à envoyer un e-mail à : notice#oldtoolbag.com (au moment de l'envoi d'un e-mail, veuillez remplacer # par @ pour signaler une fraude, et fournir des preuves pertinentes. Une fois confirmé, ce site supprimera immédiatement le contenu suspect de violation de droits d'auteur.)

Vous pourriez aussi aimer