在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,开始贴代码~

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

服务端代码:

 <?php
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 = @socket_recv($socket,$buffer,2048,0);
if ($bytes == 0){
$this->disConnect($socket);
}
else{
$key = array_search($socket, $this->sockets);
if (empty($this->handshake) || !isset($this->handshake[$key]) || !$this->handshake[$key]){
$this->doHandShake($socket, $buffer, $key);
}
else{
$buffer = $this->decode($buffer);
echo $buffer.PHP_EOL;
$key = array_search($socket, $this->sockets);
$arr = $this->sockets;
array_shift($arr);
foreach ($arr as $s){
$this->send($s, $buffer);
}
}
}
}
}
}
} function send($client, $msg){
$msg = $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 = array_search($socket, $this->sockets);
socket_close($socket);
$this->say($socket . " DISCONNECTED!");
if ($index >= 0){
echo 'unset index is:'.PHP_EOL;
unset($this->sockets[$index]);
}
}
function doHandShake($socket, $buffer, $handKey){
$this->log("\nRequesting handshake...");
$this->log($buffer);
list($resource, $host, $origin, $key) = $this->getHeaders($buffer);
$this->log("Handshaking...");
$upgrade = "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 = socket_write($socket, $upgrade, strlen($upgrade));
$this->handshake[$handKey]=true;
$this->log("Done handshaking...");
return true;
} function getHeaders($req){
$r = $h = $o = $key = null;
if (preg_match("/GET (.*) HTTP/" ,$req,$match)) { $r = $match[1]; }
if (preg_match("/Host: (.*)\r\n/" ,$req,$match)) { $h = $match[1]; }
if (preg_match("/Origin: (.*)\r\n/" ,$req,$match)) { $o = $match[1]; }
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$req,$match)) { $key = $match[1]; }
return array($r, $h, $o, $key);
} function calcKey($key){
//基于websocket version 13
$accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
return $accept;
} function decode($buffer) {
$len = $masks = $data = $decoded = null;
$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++) {
$decoded .= $data[$index] ^ $masks[$index % 4];
}
return $decoded;
} function frame($s){
$a = str_split($s, 125);
if (count($a) == 1){
return "\x81" . chr(strlen($a[0])) . $a[0];
}
$ns = "";
foreach ($a as $o){
$ns .= "\x81" . chr(strlen($o)) . $o;
}
return $ns;
} function say($msg = ""){
echo $msg . "\n";
}
function log($msg = ""){
if ($this->debug){
echo $msg . "\n";
}
}
} new WS('localhost', 4000);

客户端代码(H5):

 <html>
<head>
<title>demo</title>
<script src="https://cdn.bootcss.com/jquery/1.9.1/jquery.min.js"></script>
</head>
<body>
<input type="text" id="content">
<input type="button" value="send" id="send">
<script type="text/javascript">
var ws = new WebSocket("ws://localhost:4000");
ws.onopen = function(){
console.log("握手成功");
}
ws.onmessage = function(e){
console.log("message:" + e.data);
}
ws.onerror = function(){
console.log("error");
}
$("#send").click(function(){
content = $("#content").val();
console.log(content);
ws.send(content);
})
</script>
</body>
</html>

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

代码解析:

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

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

php实现socket推送技术的更多相关文章

  1. php + h5 实现socket推送技术

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

  2. PHP ServerPush (推送) 技术的探讨

    2016年11月29日17:51:03 转自:http://www.cnblogs.com/hnrainll/archive/2013/05/07/3064874.html 需求: 我想做个会员站内通 ...

  3. Web端服务器推送技术原理分析及dwr框架简单的使用

    1 背景 “服务器推送技术”(ServerPushing)是最近Web技术中最热门的一个流行术语.它是继“Ajax”之后又一个倍受追捧的Web技术.“服务器推送技术”最近的流行跟“Ajax ”有着密切 ...

  4. 基于Web的数据推送技术(转)

    基于Web的数据推送技术 对于实时性数据显示要求比较高的系统,比如竞价,股票行情,实时聊天等,我们的解决方案有以下几种.1. HTTP请求发送模式,一般可以基于ajax的请求,比如每3秒一次访问下服务 ...

  5. 深入了解 Dojo 的服务器推送技术

    国内私募机构九鼎控股打造APP,来就送 20元现金领取地址:http://jdb.jiudingcapital.com/phone.html 内部邀请码:C8E245J (不写邀请码,没有现金送) 国 ...

  6. Android推送技术研究

    前言 最近研究Android推送的实现, 研究了两天一夜, 有了一点收获, 写下来既为了分享, 也为了吐槽. 需要说明的是有些东西偏底层硬件和通信行业, 我对这些一窍不通, 只能说说自己的理解. 为什 ...

  7. 关于 实时推送技术--WebSocket的 知识分享

    今天学习了关于WebSocket的知识,觉得挺有用的,在这记录一下,也和大家分享一下!!有兴趣的可以看看哦 WebSocket简介 Web领域的实时推送技术,也被称作Realtime技术.这种技术要达 ...

  8. Web端server推送技术原理分析及dwr框架简单的使用

    1 背景 "server推送技术"(ServerPushing)是近期Web技术中最热门的一个流行术语.它是继"Ajax"之后又一个倍受追捧的Web技术.&qu ...

  9. PHP ServerPush (推送) 技术

    用来代替ajax的请求 转自:http://blog.163.com/bailin_li/blog/static/17449017920124811524364/ 需求: 我想做个会员站内通知的功能. ...

随机推荐

  1. js 获取每月有几周,根据年月周获取该周从周一到周日的日期等方法

    本文基于react-native 本人在用react-native写一个关于课程表的APP时需要课程表按照日期周期显示,网上查了许多方法,都没有达到自己想要的效果,根据一些方法的参考,再根据自己思维写 ...

  2. linux 常用命令详解

    常见Linux目录名称:/ 虚拟目录的根目录.通常不会在这里存储文件/bin 二进制目录,存放许多用户级的GNU工具/boot 启动目录,存放启动文件/dev 设备目录,Linux在这里创建设备节点/ ...

  3. 实践作业3DAY1

    今天,老师又布置了新的学习任务,关于白盒测试.感觉黑盒测试,我们用的比较多,白盒测试就相对陌生了.上课的时候老师虽然也进行了一定的点拨,外加我们学习了SPOC视频,但是并没有看到什么具体的项目,所以实 ...

  4. hdu 1068 Girls and Boys 最大独立点集 二分匹配

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1068 思路: 求一集合满足,两两之间没有恋爱关系 思路: 最大独立点集=顶点数-最大匹配数 这里给出的 ...

  5. OGNL简介

    OGNL 一:OGNL简介 OGNL的全称是Object  Graph  Navigation  Language即对象导航语音.它是一个开源项目,工作在视图层,用来取代页面中的java脚本.简化数据 ...

  6. 学习用java基于webMagic+selenium+phantomjs实现爬虫Demo爬取淘宝搜索页面

    由于业务需要,老大要我研究一下爬虫. 团队的技术栈以java为主,并且我的主语言是Java,研究时间不到一周.基于以上原因固放弃python,选择java为语言来进行开发.等之后有时间再尝试pytho ...

  7. 【福利】十一起,小冰科技所有UWP产品免费半个月

    从十月一日起(UTC协调世界时),至十月十五,小冰科技所有UWP产品免费半个月!!!!!! 注意是UTC哦,中国区,比UTC早8个小时,要等到十月一号早晨八点开始... 现在小冰科技旗下一共发布了 5 ...

  8. 零基础学习Hadoop

    零基础学习hadoop,没有想象的那么困难,也没有想象的那么容易.在刚接触云计算,曾经想过培训,但是培训机构的选择就让我很纠结.所以索性就自己学习了.整个过程整理一下,给大家参考,欢迎讨论,共同学习. ...

  9. 【POJ2823】Sliding Window

    http://poj.org/problem?id=2823 题意:你有一个长度n的序列,分别询问[1,k],[2,k+1],[3,k+2],...,[n-k+1,n]这n-k+1个区间的最大值和最小 ...

  10. java实现导出Excel(跨行,跨列)

    先来个最终结果样式: 第一步: 传参,后期可根据自己需要进行调整.我这里需要的是 quarter 代表季度 dptid 部门编号根据接受过来的参数进行文档命名. UserInfo userInfo=( ...