热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

phpsocket主动推送消息,php实现socket推送技术的示例

在socket出现之前已经有ajax定时请求、长轮询等方案,但都不能满足需求,socket就应用而生了。socket基本函数socket总结下常用的so

在socket出现之前已经有ajax定时请求、长轮询等方案,但都不能满足需求,socket就应用而生了。

socket基本函数socket

总结下常用的socket函数

服务端:socket_create 创建socket设置基本参数

socket_bind 绑定ip和端口号

socket_listen 监听

socket_accept 客户端的连接

socket_read 读取客户端的数据

socket_write 给单独客户端发送数据

socket_close 关闭连接

客户端:socket_create 创建socket设置基本参数

socket_connect 连接socket

socket_write 给服务端发送数据

socket_read 读取服务端数据

socket_close 关闭连接

H5websocket不多说了,上链接

OK,开始贴代码~

----------------------------------------------------------分割线

服务端代码:

class WS {

var $master;

var $sockets = array();

var $debug = false;//true为调试模式,输出log日志

var $handshake = array();

function __construct($address, $port){

$this->master=socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die("socket_create() failed");

socket_set_option($this->master, SOL_SOCKET, SO_REUSEADDR, 1) or die("socket_option() failed");

socket_bind($this->master, $address, $port) or die("socket_bind() failed");

socket_listen($this->master,20) or die("socket_listen() failed");

$this->sockets[] = $this->master;

$this->say("Server Started : ".date('Y-m-d H:i:s'));

$this->say("Listening on : ".$address." port ".$port);

$this->say("Master socket : ".$this->master."\n");

while(true){

$socketArr = $this->sockets;

$write = NULL;

$except = NULL;

socket_select($socketArr, $write, $except, NULL); //自动选择来消息的socket 如果是握手 自动选择主机

foreach ($socketArr as $socket){

if ($socket == $this->master){ //主机

$client = socket_accept($this->master);

if ($client <0){

$this->log("socket_accept() failed");

continue;

} else{

$this->connect($client);

}

} else {

$bytes &#61; &#64;socket_recv($socket,$buffer,2048,0);

if ($bytes &#61;&#61; 0){

$this->disConnect($socket);

}

else{

$key &#61; array_search($socket, $this->sockets);

if (empty($this->handshake) || !isset($this->handshake[$key]) || !$this->handshake[$key]){

$this->doHandShake($socket, $buffer, $key);

}

else{

$buffer &#61; $this->decode($buffer);

echo $buffer.PHP_EOL;

$key &#61; array_search($socket, $this->sockets);

$arr &#61; $this->sockets;

array_shift($arr);

foreach ($arr as $s){

$this->send($s, $buffer);

}

}

}

}

}

}

}

function send($client, $msg){

$msg &#61; $this->frame($msg);

socket_write($client, $msg, strlen($msg));

}

function connect($socket){

array_push($this->sockets, $socket);

$this->say("\n" . $socket . " CONNECTED!");

$this->say(date("Y-n-d H:i:s"));

}

function disConnect($socket){

$index &#61; array_search($socket, $this->sockets);

socket_close($socket);

$this->say($socket . " DISCONNECTED!");

if ($index >&#61; 0){

echo &#39;unset index is:&#39;.PHP_EOL;

unset($this->sockets[$index]);

}

}

function doHandShake($socket, $buffer, $handKey){

$this->log("\nRequesting handshake...");

$this->log($buffer);

list($resource, $host, $origin, $key) &#61; $this->getHeaders($buffer);

$this->log("Handshaking...");

$upgrade &#61; "HTTP/1.1 101 Switching Protocol\r\n" .

"Upgrade: websocket\r\n" .

"Connection: Upgrade\r\n" .

"Sec-WebSocket-Accept: " . $this->calcKey($key) . "\r\n\r\n"; //必须以两个回车结尾

$this->log($upgrade);

$sent &#61; socket_write($socket, $upgrade, strlen($upgrade));

$this->handshake[$handKey]&#61;true;

$this->log("Done handshaking...");

return true;

}

function getHeaders($req){

$r &#61; $h &#61; $o &#61; $key &#61; null;

if (preg_match("/GET (.*) HTTP/" ,$req,$match)) { $r &#61; $match[1]; }

if (preg_match("/Host: (.*)\r\n/" ,$req,$match)) { $h &#61; $match[1]; }

if (preg_match("/Origin: (.*)\r\n/" ,$req,$match)) { $o &#61; $match[1]; }

if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)) { $key &#61; $match[1]; }

return array($r, $h, $o, $key);

}

function calcKey($key){

//基于websocket version 13

$accept &#61; base64_encode(sha1($key . &#39;258EAFA5-E914-47DA-95CA-C5AB0DC85B11&#39;, true));

return $accept;

}

function decode($buffer) {

$len &#61; $masks &#61; $data &#61; $decoded &#61; null;

$len &#61; ord($buffer[1]) & 127;

if ($len &#61;&#61;&#61; 126) {

$masks &#61; substr($buffer, 4, 4);

$data &#61; substr($buffer, 8);

}

else if ($len &#61;&#61;&#61; 127) {

$masks &#61; substr($buffer, 10, 4);

$data &#61; substr($buffer, 14);

}

else {

$masks &#61; substr($buffer, 2, 4);

$data &#61; substr($buffer, 6);

}

for ($index &#61; 0; $index

$decoded .&#61; $data[$index] ^ $masks[$index % 4];

}

return $decoded;

}

function frame($s){

$a &#61; str_split($s, 125);

if (count($a) &#61;&#61; 1){

return "\x81" . chr(strlen($a[0])) . $a[0];

}

$ns &#61; "";

foreach ($a as $o){

$ns .&#61; "\x81" . chr(strlen($o)) . $o;

}

return $ns;

}

function say($msg &#61; ""){

echo $msg . "\n";

}

function log($msg &#61; ""){

if ($this->debug){

echo $msg . "\n";

}

}

}

new WS(&#39;localhost&#39;, 4000);

客户端代码(H5)&#xff1a;

demo

var ws &#61; new WebSocket("ws://localhost:4000");

ws.onopen &#61; function(){

console.log("握手成功");

}

ws.onmessage &#61; function(e){

console.log("message:" &#43; e.data);

}

ws.onerror &#61; function(){

console.log("error");

}

$("#send").click(function(){

content &#61; $("#content").val();

console.log(content);

ws.send(content);

})

然后执行php demo.php 开启socket(从运维那偷学一招&#xff0c;linux下执行nohup php demo.php &可以在后台执行)&#xff0c;浏览器打开多个index.html&#xff0c;就能建立通讯了。

代码解析&#xff1a;

1.属性$sockets数组保存每个accept连接(不知道这么描述对不对);

2.属性$handshake数组保存连接是否在连接状态;

以上这篇php实现socket推送技术的示例就是小编分享给大家的全部内容了&#xff0c;希望能给大家一个参考&#xff0c;也希望大家多多支持脚本之家。



推荐阅读
  • 本文介绍了Python高级网络编程及TCP/IP协议簇的OSI七层模型。首先简单介绍了七层模型的各层及其封装解封装过程。然后讨论了程序开发中涉及到的网络通信内容,主要包括TCP协议、UDP协议和IPV4协议。最后还介绍了socket编程、聊天socket实现、远程执行命令、上传文件、socketserver及其源码分析等相关内容。 ... [详细]
  • 本文介绍了使用PHP实现断点续传乱序合并文件的方法和源码。由于网络原因,文件需要分割成多个部分发送,因此无法按顺序接收。文章中提供了merge2.php的源码,通过使用shuffle函数打乱文件读取顺序,实现了乱序合并文件的功能。同时,还介绍了filesize、glob、unlink、fopen等相关函数的使用。阅读本文可以了解如何使用PHP实现断点续传乱序合并文件的具体步骤。 ... [详细]
  • 本文介绍了为什么要使用多进程处理TCP服务端,多进程的好处包括可靠性高和处理大量数据时速度快。然而,多进程不能共享进程空间,因此有一些变量不能共享。文章还提供了使用多进程实现TCP服务端的代码,并对代码进行了详细注释。 ... [详细]
  • 移动端常用单位——rem的使用方法和注意事项
    本文介绍了移动端常用的单位rem的使用方法和注意事项,包括px、%、em、vw、vh等其他常用单位的比较。同时还介绍了如何通过JS获取视口宽度并动态调整rem的值,以适应不同设备的屏幕大小。此外,还提到了rem目前在移动端的主流地位。 ... [详细]
  • php缓存ri,浅析ThinkPHP缓存之快速缓存(F方法)和动态缓存(S方法)(日常整理)
    thinkPHP的F方法只能用于缓存简单数据类型,不支持有效期和缓存对象。S()缓存方法支持有效期,又称动态缓存方法。本文是小编日常整理有关thinkp ... [详细]
  • 本文介绍了如何使用OpenXML按页码访问文档内容,以及在处理分页符和XML元素时的一些挑战。同时,还讨论了基于页面的引用框架的局限性和超越基于页面的引用框架的方法。最后,给出了一个使用C#的示例代码来按页码访问OpenXML内容的方法。 ... [详细]
  • 本文分享了一个关于在C#中使用异步代码的问题,作者在控制台中运行时代码正常工作,但在Windows窗体中却无法正常工作。作者尝试搜索局域网上的主机,但在窗体中计数器没有减少。文章提供了相关的代码和解决思路。 ... [详细]
  • 如何使用Java获取服务器硬件信息和磁盘负载率
    本文介绍了使用Java编程语言获取服务器硬件信息和磁盘负载率的方法。首先在远程服务器上搭建一个支持服务端语言的HTTP服务,并获取服务器的磁盘信息,并将结果输出。然后在本地使用JS编写一个AJAX脚本,远程请求服务端的程序,得到结果并展示给用户。其中还介绍了如何提取硬盘序列号的方法。 ... [详细]
  • 计算机存储系统的层次结构及其优势
    本文介绍了计算机存储系统的层次结构,包括高速缓存、主存储器和辅助存储器三个层次。通过分层存储数据可以提高程序的执行效率。计算机存储系统的层次结构将各种不同存储容量、存取速度和价格的存储器有机组合成整体,形成可寻址存储空间比主存储器空间大得多的存储整体。由于辅助存储器容量大、价格低,使得整体存储系统的平均价格降低。同时,高速缓存的存取速度可以和CPU的工作速度相匹配,进一步提高程序执行效率。 ... [详细]
  • 本文介绍了计算机网络的定义和通信流程,包括客户端编译文件、二进制转换、三层路由设备等。同时,还介绍了计算机网络中常用的关键词,如MAC地址和IP地址。 ... [详细]
  • 本文介绍了通过ABAP开发往外网发邮件的需求,并提供了配置和代码整理的资料。其中包括了配置SAP邮件服务器的步骤和ABAP写发送邮件代码的过程。通过RZ10配置参数和icm/server_port_1的设定,可以实现向Sap User和外部邮件发送邮件的功能。希望对需要的开发人员有帮助。摘要长度:184字。 ... [详细]
  • 关键词:Golang, Cookie, 跟踪位置, net/http/cookiejar, package main, golang.org/x/net/publicsuffix, io/ioutil, log, net/http, net/http/cookiejar ... [详细]
  • 个人学习使用:谨慎参考1Client类importcom.thoughtworks.gauge.Step;importcom.thoughtworks.gauge.T ... [详细]
  • 本文介绍了在mac环境下使用nginx配置nodejs代理服务器的步骤,包括安装nginx、创建目录和文件、配置代理的域名和日志记录等。 ... [详细]
  • 前景:当UI一个查询条件为多项选择,或录入多个条件的时候,比如查询所有名称里面包含以下动态条件,需要模糊查询里面每一项时比如是这样一个数组条件:newstring[]{兴业银行, ... [详细]
author-avatar
L呆头_383
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有