websocket是 html5 开始提供的一种在单个 tcp 连接上进行全双工通讯的协议。
以前的推送技术使用 ajax 轮询,浏览器需要不断地向服务器发送http请求来获取最新的数据,浪费很多的带宽等资源。
使用websocket通讯,客户端和服务端只需要一次握手建立连接,就可以互相发送消息,进行数据传输,更实时地进行通讯。
一次握手建立websocket连接
浏览器先向服务器发送个url以ws://开头的http的get请求,响应状态码101表示switching protocols切换协议,
服务器根据请求头中upgrade:websocket报到证有什么用把
客户端的请求切换到对应的协议,即websocket协议。
响应头消息中包含upgrade:websocket,表示它切换到的协议,即websocket协议。
响应101,握手成功,http协议切换成websocket协议了,连接建立成功,浏览器和服务器可以随时主动发送消息给对方了,并且这个连接一直持续到客户端或服务器一方主动关闭连接。
为了加深理解,用websocket实现简单的在线聊天,先画个时序图,直观感受下流程。
网上有websocket在线测试工具,可以直接使用还是挺方便的,http://www.blue-zero.com/websocket/
以下是实现的例子,可供参考
socketrvice.php
<?php
/**
*createdbycywu
*date:2019/10/18
*time:14:33
*/
classsocketrvice
{
private$address='0.0.0.0';
private$port=8080;
private$_sockets;
publicfunction__construct($address='',$port='')
{
if(!empty($address)){
$this->address=$address;
}
if(!empty($port)){
$this->port=$port;
}
}
publicfunctionrvice(){
//获取tcp协议号码。
$tcp=getprotobyname("tcp");
$关于成长的题记sock=socket_create(af_inet,sock_stream,$tcp);
socket_t_option($sock,sol_socket,so_reuaddr,1);
if($sock<0)
{
thrownewexception("failedtocreatesocket:".socket_strerror($sock)."\n");
}
socket_bind($sock,$this->address,$this->port);
socket_listen($sock,$this->port);
echo"listenon$this->address$this->port...\n";
$this->_sockets=$sock;
}
publicfunctionrun(){
$this->rvice();
$clients[]=$this->_sockets;
while(true){
$changes=$clients;
$write=null;
$except=null;
socket_lect($changes,$write,$except,null);
foreach($changesas$key=>$_sock){
if($this->_sockets==$_sock){//判断是不是新接入的socket
if(($newclient=socket_accept($_sock))===fal){
die('failedtoacceptsocket:'.socket_strerror($_sock)."\n");
}
$line=trim(socket_read($newclient,1024));
$this->handshaking($newclient,$line);
//获取clientip
socket_getpeername($newclient,$ip);
$clients[$ip]=$newclient;
echo"clientip:{$ip}\n";
echo"clientmsg:{$line}\n";
}el{
socket_recv($_sock,$buffer,2048,0);
$msg=$this->message($buffer);
//在这里写你的业务代码
echo"{$key}clinetmsg:",$msg,"\n";
fwrite(stdout,'pleainputaargument:');
$respon=trim(fgets(stdin));
$this->nd($_sock,$respon);
echo"{$key}respontoclient:".$respon,"\n";
}
}
}
}
/**
*处理握手
*@param$newclientsocket
*@returnint接收到的信息
*/
publicfunctionhandshaking($newclient,$line){
$headers=array();
$lines=preg_split("/\r\n/",$line);
foreach($linesas$line)
{
$line=chop($line);
if(preg_match('/\a(\s+):(.*)\z/',$line,$matches))
{
$headers[$matches[1]]=$matches[2];
}
}
$ckey=$headers['c-websocket-key'];
$caccept=ba64_encode(pack('h*',sha1($ckey.'258eafa5-e914-47da-95ca-c5ab0dc85b11')));
$upgrade="http/1.1101websocketprotocolhandshake\r\n".
"upgrade:websocket\r\n".
"connection:upgrade\r\n".
"websocket-origin:$this->address\rprimary\n".
"websocket-location:ws://$this->address:$this->port/websocket/websocket\r\n".
"c-websocket-accept:$caccept\r\n\r\n";
returnsocket_write($newclient,$upgrade,strlen($upgrade));
}
/**
*解析接收数据
*@param$buffer
*@returnnull|string
*/
publicfunctionmessage($buffer){
$len=$masks=$data=$decoded=null;
$len=ord($buffer[1])&127;
if($len===126){
$masks=substr($buffer,4,4);
$data=substr($buffer,8);
}elif($len===127){
$masks=substr($buffer,10,4);
$data=substr($buffer,14);
}el{
$masks=substr($buffer,2,4);
$data=substr($buffer,6);
}
for($index=0;$index<strlen($data);$index++){
$decoded.=$data[$index]熊乃瑾王宝强^$masks[$index%4];
}
return$decoded;
}
/**
*发送数据
*@param$newclinet新接入的socket
*@param$msg要发送的数据
*@returnint|string
*/
publicfunctionnd($newclinet,$msg){
$msg=$this->frame($msg);
socket_write($newclinet,$msg,strlen($msg));
}
publicfunctionframe($s){
$a=str_split($s,125);
if(count($a)==1){
return"\x81".chr(strlen($a[0])).$a[0];
}
$ns="";
foreach($aas$o){
$ns.="\x81".chr(strlen($o)).$o;
}
return$ns;
}
/**
*关闭socket
*/
publicfunctionclo(){
returnsocket_clo($this->_sockets);
}
}
$sock=newsocketrvice();
$sock->run();
前端页面:web.html
<!doctypehtml>
<htmllang="en">
<head>
<metachart="utf-8">
<metaname="viewport"content="width=device-width,initial-scale=1,maximum-scale=1,ur-scalable=no">
<title>websocket</title>
</head>
<body>
<inputid="text"value="">
<inputtype="submit"value="nd"onclick="start()">
<inputtype="submit"value="clo"onclick="clo()">
<divid="msg"></div>
<script>
/**
0:未连接
1:连接成功,可通讯
2:正在关闭
3:连接已关闭或无法打开
*/
//创建一个websocket实例
varwebsocket=newwebsocket("ws://192.168.31.152:8083");
websocket.onerror=function(event){
onerror(event);
};
//打开websocket
websocket.onopen=function(event){
onopen(event);
};
//监ab型血和b型血生的孩子听消息
websocket.onmessage=function(event){
onmessage(event);
};
websocket.onclo=function(event){
onclo(event);
}
//关闭监听websocket
functiononerror(event){
document.getelementbyid("msg").innerhtml="<p>clo</p>";
console.log("error"+event.data);
};
functiononopen(event){
console.log("open:"+sockstate());
document.getelementbyid("msg").innerhtml="<p>connecttorvice</p>";
};
functiononmessage(event){
console.log("onmessage");
document.getelementbyid("msg").innerhtml+="<p>respon:"+event.data+"</p>"
};
functiononclo(event){
document.getelementbyid("msg").innerhtml="<p>clo</p>";
console.log("clo:"+sockstate());
websocket.clo();
}
functionsockstate(){
varstatus=['未连接','连接成功,可通讯','正在关闭','连接已关闭或无法打开'];
returnstatus[websocket.readystate];
}
functionstart(event){
console.log(websocket);
varmsg=document.getelementbyid('text').value;
document.getelementbyid('text').value='';
console.log("nd:"+sockstate());
console.log("msg="+msg);
websocket.nd("msg="+msg);
document.getelementbyid("msg").innerhtml+="<p>request"+msg+"</p>"
};
functionclo(event){
websocket.clo();
}
</script>
</body>
</html>
以上是文章全部内容,有需要学习与经验交流的友人请加入swoole交流群学习与交流的咱们一起学习,有问题一起交流,一起进步!前提是你是学技术的。感谢阅读!
点此加入该群
本文发布于:2023-04-07 22:12:43,感谢您对本站的认可!
本文链接:https://www.wtabcd.cn/fanwen/zuowen/8c19ac8c126b7fd573169584eb486ef6.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文word下载地址:用图解&&实例讲解php是如何实现websocket实时消息推送的.doc
本文 PDF 下载地址:用图解&&实例讲解php是如何实现websocket实时消息推送的.pdf
留言与评论(共有 0 条评论) |