在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. Unity灯光烘焙

    Unity3D烘焙技术 一.Light灯光场景烘焙1.理论理解:(1)烘焙背景:在一个场景中,由于灯光组件起到实时渲染的效果,并直接与计算机硬件GPU渲染器进行交互作用,因此对计算机显卡性能不良,以至 ...

  2. Python函数中如何定义参数

    一.位置参数:根据函数定义时的参数位置传递参数#形参和实参的个数必须一致def fun1(): print("运行结果") print("this is fun1(),n ...

  3. webuploader 实现图片批量上传

    1.导入资源 2.JSP代码 <div class="page-container"> <div class="row cl"> < ...

  4. mysql常用的操作

    数据库的常用操作:create database db1; #创建数据库show databases; #查看所有数据库show create database db1;#查看创建的指定数据库alte ...

  5. 【转】Nginx反向代理和负载均衡

    原文链接:http://www.cnblogs.com/shuoer/p/7820899.html Nginx反向代理和负载均衡 环境说明 由于我使用的是windows系统,所以我用虚拟机虚拟出来了3 ...

  6. P1092 虫食算

    题目传送:https://www.luogu.org/problem/show?pid=1092 #include <iostream> #include <cstring> ...

  7. 2016普及组t3海港

    好的,说说这道题的思路,爆搜队列嘛: 用一个结构体队列存每个人来的时间和他的国籍,用一个vis数组存每个人来的次数,是第一次来sum便加一. 然后从前面第一个人开始扔(原谅我用这个词,因为我找不到更好 ...

  8. 翻译连载 | 附录 C:函数式编程函数库-《JavaScript轻量级函数式编程》 |《你不知道的JS》姊妹篇

    原文地址:Functional-Light-JS 原文作者:Kyle Simpson-<You-Dont-Know-JS>作者 关于译者:这是一个流淌着沪江血液的纯粹工程:认真,是 HTM ...

  9. 【OCR技术系列之二】文字定位与切割

    要做文字识别,第一步要考虑的就是怎么将每一个字符从图片中切割下来,然后才可以送入我们设计好的模型进行字符识别.现在就以下面这张图片为例,说一说最一般的字符切割的步骤是哪些. 当然,我们实际上要识别的图 ...

  10. 浏览器出现Cannot set property 'onclick' of null的问题

    Part1: 当js文件放在head里面时,如果绑定了onclick事件,就会出现这样的错误, 是因为W3School的写法是浏览器先加载完按钮节点才执行的js,所以当浏览器自顶向下解析时,找不到on ...