返回顶部
首页 > 资讯 > 后端开发 > PHP编程 >WebSocket的通信原理和使用
  • 702
分享到

WebSocket的通信原理和使用

websocketphp 2023-09-13 12:09:56 702人浏览 独家记忆
摘要

一、什么是websocket? 1.1 简介 WEBSocket协议是基于tcp的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只

一、什么是websocket

1.1 简介

WEBSocket协议是基于tcp的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只需要完成一次握手,两者之间就直接可以创建持久性的连接,并进行双向数据传输,客户端和服务器之间的数据交换变得更加简单。

1.2 WebSocket的优势

现在,很多网站为了实现推送技术,所用的技术都是Ajax轮询。轮询是在特定的时间间隔(如每1秒),由浏览器对服务器发出Http请求,然后由服务器返回最新的数据给客户端的浏览器。

这种传统的模式带来很明显的缺点,即浏览器需要不断的向服务器发出请求。然而HTTP请求可能包含较长的头部,其中真正有效的数据可能只是很小的一部分,显然这样会浪费很多的带宽等资源。HTML5定义的WebSocket协议优势如下:

小Header,互相沟通的Header非常小,只有2Bytes左右。
2、服务器不再被动接收到浏览器的请求之后才返回数据,而是在有新数据时就主动推送给浏览器。
3、WebSocket协议能更好的节省服务器资源和带宽,并且能够更实时地进行通讯。

1.3 WebSocket的原理 

▪ Websocket协议由RFC 6455定义,协议分为两个部分: 握手阶段和全双工通信阶段。

  客户端发送的header内容 

GET /nickname11 HTTP/1.1 Host: 127.0.0.1:9090Connection: UpgradeUpgrade: websocketSec-WebSocket-Extensions: permessage-deflate; client_max_window_bitsSec-WebSocket-Key: wJdg8v4EJiDsIZg5+s0hY8RUQ2A=Sec-WebSocket-Version: 13Origin: http://127.0.0.1

  服务端响应的header内容,这里的Sec-WebSocket-Accept要根据发送的Sec-WebSocket-Key来处理算出来,计算方法:base64_encode(sha1(websocket_key + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11", true)) 。

HTTP/1.1 101 Switching ProtocolUpgrade: WebSocketSec-WebSocket-Version: 13Connection: UpgradeSec-WebSocket-Accept: wJdg8v4EJiDsIZg5+s0hY8RUQ2A=

▪ Websocket协议的握手阶段是使用的HTTP协议。

▪ Websocket协议的“全双工”消息通信是基于 TCP/IP 的协议集之上的,客户端和服务端可随时发送数据。协议连接是“ws”或者加密的“wss”。

▪  通信的数据是基于“帧(frame)”的,可以传输文本数据,也可以直接传输二进制数据,效率高。

 一条消息(message)可由一个或多个帧(Frame)组成,很多时候会将帧和消息混用,因为大部分时候一条消息只使用一个帧

二、使用PHP实现WebSocket通信

server.php(服务端) 

master = $this->createWebSocket();         //创建socket连接池        $this->sockets=array($this->master);    }public function start(){while (true) {$changes=$this->sockets;            $write=NULL;            $except=NULL;            //设置非阻塞,让多个连接能同时正常往下执行@socket_select($changes, $write, $except, NULL);foreach($changes as $socket){//判断是否新的socket连接if($socket == $this->master){$client=socket_accept($socket);$key=uniqid();$this->sockets[]=$client;$this->users[$key]=array(                        'client'=>$client,                        'is_shake'=>0                    );}else{$len=0;                    $buffer='';do{                        $l=socket_recv($socket,$buf,1024,0);                        $len+=$l;                        $buffer.=$buf;                    }while($l==1024);$key = $this->search($socket);// 如果接收的信息长度小于7,则该client的socket为断开连接if($len<7){                        unset($this->users[$key]);            socket_close($socket);                        continue;                    }                    //判断连接是否已握手                    if(!$this->users[$key]['is_shake']){                    $this->shake($key, $buffer);                    }else{                    //接收客户端发送消息                    $buffer = $this->getMsg($buffer);                        if($buffer === false){continue;                        }                        //发送消息                        $this->sendMsg($key,$buffer);                    }}}}}protected function intoRedis($data){$redis = new Redis();$redis->pconnect($this->redisIp, $this->redisPort, $this->redisLength);$redis->lpush("ws_".$this->getMd5Key($data['username']), json_encode($data));return true;}protected function search($socket){        foreach ($this->users as $key=>$val){            if($socket==$val['client'])            return $key;        }        return false;    }    protected function shake($key, $buf)    {    preg_match("/Sec-WebSocket-Key: (.*)\r\n/i",$buf,$match);    //用于服务端计算Sec_WebSocket_Accept的固定的字符串    $keyStr = '258EAFA5-E914-47DA-95CA-C5AB0DC85B11';        $res= "HTTP/1.1 101 Switching Protocol".PHP_EOL            ."Upgrade: WebSocket".PHP_EOL            ."Sec-WebSocket-Version: 13".PHP_EOL            ."Connection: Upgrade".PHP_EOL            ."Sec-WebSocket-Accept: " . base64_encode(sha1($match[1].$keyStr ,true)) .PHP_EOL.PHP_EOL;  // 注意需要两个换行        // 向客户端应答 Sec-WebSocket-Accept        socket_write($this->users[$key]['client'], $res, strlen($res));        //对已经握手的client做标志        $this->users[$key]['is_shake'] = 1;        return true;    }protected function sendMsg($key, $buffer){$index = strpos($buffer, ":");        $data = [        'username' => substr($buffer, 0, $index),        'msg' => substr($buffer, ($index+1)),        'time' => date("Y-m-d H:i:s", time()),        ];        foreach($this->users as $val){        $msg = $this->buildMsg(json_encode($data));            socket_write($val['client'], $msg, strlen($msg));        }        //通过redis记录消息        $this->intoRedis($data);        echo "
";        print_r($data);}// 编码服务端向客户端发送的内容protected function buildMsg($msg) {    $frame = [];    $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;    }    $data = '';    $l = strlen($msg);    for ($i = 0; $i < $l; $i++) {        $data .= dechex(ord($msg{$i}));    }    $frame[2] = $data;    $data = implode('', $frame);    return pack("H*", $data);}// 解析客户端向服务端发送的内容protected function getMsg($buffer) {    $res = '';    $len = ord($buffer[1]) & 127;    if ($len === 126) {        $masks = substr($buffer, 4, 4);        $data = substr($buffer, 8);    } else if ($len === 127) {        $masks = substr($buffer, 10, 4);        $data = substr($buffer, 14);    } else {        $masks = substr($buffer, 2, 4);        $data = substr($buffer, 6);    }    for ($index = 0; $index < strlen($data); $index++) {        $res .= $data[$index] ^ $masks[$index % 4];    }    return $res;}//建立WebSocket链接protected function createWebSocket(){    $server = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);    socket_set_option($server, SOL_SOCKET, SO_REUSEADDR, 1);//1代表接受所有的数据包    socket_bind($server, $this->ip, $this->port);    socket_listen($server);        echo 'Socket连接创建成功,时间: '.date('Y-m-d H:i:s').PHP_EOL;    return $server;}protected function getMd5Key($username){return md5($username."WebSocket");}}$server = new server();$act = isset($_POST['act']) ? $_POST['act'] : 'start';if($act == 'start'){$server->start();}else if($act == 'getAllMsg'){$server->getRedis();}

getredis.php(获取存在redis的历史消息) 

500, 'msg'=>'act参数不能为空', 'data'=>[]]);exit;}if($act != 'getAllMsg'){echo json_encode(['code'=>500, 'msg'=>'act传参错误', 'data'=>[]]);exit;}$redisIp = '127.0.0.1';$redisPort = 6379;$redisLength = 1024*600;$redis = new Redis();$redis->pconnect($redisIp, $redisPort, $redisLength);$keys = $redis->keys("ws_*");$data = [];if($keys){foreach($keys as $key){$res = $redis->lGetRange($key, 0, -1);if($res){foreach($res as &$val){$val = json_decode($val, JSON_UNESCAPED_UNICODE);$val['time_stamp'] = strtotime($val['time']);}$data = array_merge($res, $data);}}}if($data){$sort = array_column($data, 'time_stamp');array_multisort($sort, SORT_ASC, $data);}echo json_encode(['code'=>200, 'msg'=>'获取成功', 'data'=>$data]);exit;

chat.html(客户端)

   WebSocket聊天室

状态栏

当前用户: 在线情况:离线    


聊天记录栏

webSocket事件输出栏

来源地址:https://blog.csdn.net/m0_68949064/article/details/127729569

--结束END--

本文标题: WebSocket的通信原理和使用

本文链接: https://lsjlt.com/news/405936.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • WebSocket的通信原理和使用
    一、什么是WebSocket? 1.1 简介 WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信,即允许服务器主动发送信息给客户端。因此,在WebSocket中,浏览器和服务器只...
    99+
    2023-09-13
    websocket php
  • Socket的通信原理和使用
     目录 一、什么是 Socket? 二、Socket 通信过程         2.1 通信过程介绍        2.2 实现TCP建立连接的三次握手过程  三、 使用Socket进行通信【php】         3.1 PHP中So...
    99+
    2023-09-06
    网络 php
  • 如何使用PHP和WebSocket实现实时通信
    随着互联网技术的不断发展,实时通信已经成为了日常生活中不可缺少的一部分。利用WebSockets技术可以实现高效、低延迟的实时通信,而PHP作为互联网领域使用最广泛的开发语言之一,也提供了相应的WebSocket支持。本文将为大家介绍如何使...
    99+
    2023-12-17
    PHP websocket 实时通信
  • react使用websocket实时通信方式
    目录使用websocket实时通信创建公共组件在react组件中的使用websocket在不同情形下的使用1.在react中使用websocket2.websocket在小程序中使用...
    99+
    2024-04-02
  • Socket通信原理和实践
    目录TCP/IP、UDP、Socket什么是TCP/IP、UDP?Socket在哪里呢?Socket是什么呢?你会使用它们吗?1、网络中进程之间如何通信?2、什么是Socket?so...
    99+
    2024-04-02
  • 使用 Spring Boot 实现 WebSocket实时通信
    在开发 Web 应用程序时,我们有时需要将服务端事件推送到连接的客户端。但 HTTP 并不能做到。客户端打开与服务端的连接并请求数据,但服务端不能打开与客户端的连接并推送数据。为了解决这个限制,我们可以建立了一个轮询模式,网页会间隔地轮询服...
    99+
    2023-05-30
    spring boot websocket
  • golang函数和管道通信的原理
    go 语言中函数和管道结合使用实现进程间通信。函数可将管道作为参数传递,通过管道发送或接收数据。管道是无缓冲通道,可用于在 goroutine 之间发送和接收数据,并支持无向和有向管道。...
    99+
    2024-05-04
    golang 管道 作用域
  • 微信小程序如何使用websocket通讯的demo
    这篇文章主要为大家展示了“微信小程序如何使用websocket通讯的demo”,内容简而易懂,条理清晰,希望能够帮助大家解决疑惑,下面让小编带领大家一起研究并学习一下“微信小程序如何使用websocket通...
    99+
    2024-04-02
  • 怎么用Node.js实现WebSocket通信
    本篇内容介绍了“怎么用Node.js实现WebSocket通信”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!node的依赖包node中实现W...
    99+
    2023-07-04
  • 基于Node.js的WebSocket通信实现
    node的依赖包 node中实现Websocket的依赖包有很多,websocket、ws均可,本文选取ws来实现,首先安装依赖 npm install ws 聊天室实例 假如A,B,C,D用户均通过...
    99+
    2022-06-04
    通信 Node js
  • WebSocket的通信模式是什么
    今天小编给大家分享一下WebSocket的通信模式是什么的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来...
    99+
    2024-04-02
  • PHP和WebSocket: 实现即时通信的优化方法
    PHP和WebSocket: 实现即时通信的优化方法引言:随着互联网的快速发展,即时通信成为人们生活中必不可少的一部分。而在建立一个高效和可靠的即时通信系统中,WebSocket技术的应用变得越来越普遍,它可以实现双向实时通信,大大提高了用...
    99+
    2023-12-17
    优化 PHP websocket
  • Zigbee无线通信原理
    Zigbee是一种低功耗、短距离、自组织网络的无线通信技术。它基于IEEE 802.15.4标准,主要应用于物联网、智能家居和工业自...
    99+
    2023-09-20
    Zigbee
  • 如何在golang中使用WebSocket进行跨平台通信
    WebSocket是一种用于在Web浏览器和服务器之间进行实时双向通信的技术。它提供了一种可靠的方式来发送和接收数据,并且比传统的HTTP请求-响应机制更加高效、快速。在golang中,我们可以使用第三方库来支持WebSocket通信,本文...
    99+
    2023-12-18
    Golang websocket 跨平台通信
  • 如何使用Go语言实现多线程Websocket通信
    在近年来,实时通信已经成为了一种基本的需要。WebSocket则更是实时通信当中的佼佼者,它能够更快速、有效地实现客户端和服务器端之间的实时通信。而Go语言也作为近年来较火热的一种语言,被广泛应用于实时通信中。利用Go语言的优点以及多线程处...
    99+
    2023-12-14
    多线程 Go语言 Websocket通信
  • 怎么用websocket实现前后端通信
    这篇文章主要介绍了怎么用websocket实现前后端通信,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。 websocket通信是很好玩的,...
    99+
    2024-04-02
  • WebSocket与实时通信的应用案例分析
    随着互联网的发展和技术的进步,实时通信在各种应用中变得越来越重要。而传统的基于HTTP的请求-响应模式往往无法满足实时通信的需求,因此WebSocket作为一种新的协议应运而生。WebSocket协议基于TCP,允许在客户端和服务器之间建立...
    99+
    2023-10-21
    WebSocket:WebSocket是一种协议 支持实时通信。关键词:WebSocket
  • WebSocket中通信过程的示例分析
    小编给大家分享一下WebSocket中通信过程的示例分析,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是 WebSocket...
    99+
    2024-04-02
  • 如何使用WebSocket网络通信协议开发聊天室
    本篇内容主要讲解“如何使用WebSocket网络通信协议开发聊天室”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何使用WebSocket网络通信协议开发聊天室...
    99+
    2024-04-02
  • 如何在Golang中使用WebSocket实现一个通信功能
    本篇文章给大家分享的是有关如何在Golang中使用WebSocket实现一个通信功能,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。什么是golanggolang 是Google...
    99+
    2023-06-06
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作