English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Recently, while building a live broadcast room with live chat in the company, I just needed to use chatsever, so I studied html5The websocket implementation has achieved two-way communication, based on the experience of predecessors, I have been working on a chat room for several days and achieved functions such as sending pictures, sending QQ emojis, group chat and private chat, and I would like to share it with everyone for reference and learning. Experts can ignore it.
front-end: 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 webpage chat room 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=''">Clear Screen</a> </div> <div class="rin"> <button id="sd">Send</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('Your browser does not support WebSocket. It is recommended to use Google Chrome or 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 = ['Intelligent','Cunning','Cute','Beautiful','Cunning','Kind','Handsome','Funny']; var Arr2 = ['Big Grey Wolf','Little White Rabbit','Mammoth Tiger','Alien','Pikachu','HelloKitty','Wu Yifan','Xue Ziqian']; 1 = Math.floor(Math.random() * Arr1.length + 1>-1; 2 = Math.floor(Math.random() * Arr2.length + 1>-1; var n=Arr1[ran1]+Arr2[ran2]; //The following five lines are used to generate user nicknames randomly. For custom usernames, comment out the above five lines and uncomment the following two lines. // //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">exit chat room</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>hello<a>'+da.name+'</a>join</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); } 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]; } 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(){ if(!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; if(!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); for(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+'}'; if(!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){ if(!so){ st(); return false; } if(key=='all'){ alert('Due to resource limitations, sending images can only be done in private chat'); return false; } var f=ev.target.files[0]; if(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>
Backend code: 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();//Received data private $slen=array();//Total length of data private $sjen=array();//Length of received data private $ar=array();//Encryption key 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 ]); } $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); } $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+=$data .= chr($mask[$n 2) { ]= hexdec(substr($msg[4$i,1],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; } 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; } $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; } //User joins 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'; } $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 Sender's code $key Receiver's 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)); } } socket_write($this->users[$k]['socket'],$str,strlen($str)); socket_write($this->users[$key]['socket'],$str,strlen($str)); } } //User logout 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, echo iconv('utf-8','gbk//IGNORE,$str); } } ?>
Many students reported that my source code project still reported errors and could not be run, here are the detailed installation and deployment steps.
First, unzip the downloaded source code and place it in the web directory, for example, mine is applications/Xampp/xamppfiles/htdocs/phpb/webSocket
Path
Then use the command line tool cd into this directory and run the command:
php websocket.php
Running effect picture:
Command line operation
Then open the Apache server, access http: in the browser//localhost/phpb/webSocket/client.html
Running effect picture:
Source code link:webSocket-php-chatsever_jb51.rar
That's all for this article, I hope it will be helpful to everyone's learning, and I also hope everyone will support the呐喊 tutorial more.
Declaration: The content of this article is from the network, the copyright belongs to the original author, the content is contributed and uploaded by Internet users spontaneously, this website does not own the copyright, does not undergo artificial editing, nor does it bear relevant legal liability. If you find any suspected copyright content, please send an email to: notice#oldtoolbag.com (Please replace # with @ when sending an email to report, and provide relevant evidence. Once verified, this site will immediately delete the infringing content.)