English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Kürzlich habe ich im Büro eine Bild- und Text-Live-Sendung erstellt und musste genau chatsever verwenden. Ich habe mich ein wenig mit HTML beschäftigt.5Der WebSocket-Client hat eine bidirektionale Kommunikation implementiert. Basierend auf der Erfahrung anderer habe ich in den letzten Tagen eine Chatroom erstellt, die das Senden von Bildern, das Senden von QQ-Gesichtsausdrücken und Funktionen wie Gruppenchat und Privatchat ermöglicht. Ich teile dies speziell mit Anfängern zur Referenz und zum Lernen, und erfahrene Experten können dies ignorieren.
前端: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 Web-Chatroom 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> (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=Arr11]+Arr22 //Die folgenden fünf Zeilen sind Methoden zur zufälligen Generierung von Benutzernamen. Bitte beachten Sie, dass, wenn Sie einen Benutzernamen selbst festlegen möchten, die folgenden fünf Zeilen kommentiert werden können und die folgenden zwei Zeilen dekommentiert werden können. // //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">Abmelden vom Chatroom</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>Willkommen<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(){ Wenn (!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(); } } /</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; Wenn (!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(); mit (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+}; Wenn (!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) { Wenn (!so) { st(); return false; } Wenn (key == 'all') { alert('Wegen Ressourcenbeschränkungen kann das Bild nur in einer privaten Nachricht gesendet werden'); return false; } var f = ev.target.files[0]; Wenn (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();//Bereits empfangene Daten private $slen=array();//Gesamtlänge der Daten private $sjen=array();//Länge der empfangenen Daten private $ar=array();//Verschlüsselungsschlüssel 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; } //用户加入 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)); } } //用户退出 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); } } ?>
许多同学反映我的源码项目仍然报错,无法运行,以下为详细安装部署步骤。
首先将下载的源代码解压放置到web目录下,例如我的就是applications/Xampp/xamppfiles/htdocs/phpb/websocket
路径
然后使用命令行工具cd进入这个目录,运行命令:
php websocket.php
运行效果图:
命令行操作
接着打开Apache服务器,在浏览器访问http://localhost/phpb/websocket/client.html
运行效果图:
源码链接:webSoket-php-chatsever_jb51.rar
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持呐喊教程。
声明:本文内容来自网络,版权属于原作者。内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未进行人工编辑处理,也不承担相关法律责任。如果您发现涉嫌版权的内容,欢迎发送邮件至:notice#oldtoolbag.com(在发送邮件时,请将#替换为@进行举报,并提供相关证据。一经查实,本站将立即删除涉嫌侵权内容。)