项目需要使用websocket推送最新订单,客户服务器非linux不支持swoole,因此使用原生,直接上代码
(1).PHP服务端
<?php ini_set('error_reporting', E_ALL ^ E_NOTICE); ini_set('display_errors', 1); set_time_limit(0); $address = '127.0.0.1'; $port = 6936; //01.创建一个套接字(参数1是支持ipv4的TCP/UDP,参数2是套接字使用的类型,参数3是domain下具体协议) $sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP) or die('Create Socket Failed'); //02.设置socket的参数(参数1是资源句柄,参数2是ip地址,参数3是挂起本脚本的端口) socket_bind($sock, $address, $port) or die('Could not bind to address'); //03.开始监听来自本端口的所有连接 socket_listen($sock); //04.设置为非阻塞 socket_set_nonblock($sock); //05.保存所有的客户端state记录是否握手,shopid记录店铺id /* array( array('client'=>$sock1,'state'=>0,'shopid'=>0), array('client'=>$sock2,'state'=>0,'shopid'=>1), ) */ $client = array(); //06.while挂起进程来处理webscoket while (true) { //检测到新client,加入client组,并记录是否握手 if ($newsock = @socket_accept($sock)) { if (is_resource($newsock)) { //给新检测到的client回应 socket_write($newsock, "", 2) . chr(0); //并且将其加入client队伍中 array_push($client,array('client'=>$newsock,'state'=>0)); } } if (count($client)) { foreach ($client AS $k => $v) { //是否获取到数据 if (@socket_recv($v['client'], $string, 1024, 0) === 0) { unset($client[$k]); socket_close($v['client']); } else { //已经握手可以直接发送消息 if ($v['state'] == 1) { //握手完成的第一次,可以直接拿到client发送来的完整数据 if($string!=''){ $clientmsg=unmask($string); echo $clientmsg;//这就是client发送来的数据 } $data = array('12345', '上山打老虎','客户端的小妹妹你好'); $data = json_encode($data); $data = mask($data); @socket_write($v['client'], $data, strlen($data)); } //未握手先完成握手 else { doHandShake($v['client'], $string); $client[$k]['state']=1; } } } } sleep(1); } //握手方法 function doHandShake($socket, $buffer) { list($resource, $host, $origin, $key) = getHeaders($buffer); $upgrade = "HTTP/1.1 101 Switching Protocol\r\n" . "Upgrade: websocket\r\n" . "Connection: Upgrade\r\n" . "Sec-WebSocket-Accept: " . calcKey($key) . "\r\n\r\n"; //必须以两个回车结尾 socket_write($socket, $upgrade, strlen($upgrade)); } //获取请求头 function getHeaders($buffer) { $r = $h = $o = $key = null; if (preg_match("/GET (.*) HTTP/", $buffer, $match)) { $r = $match[1]; } if (preg_match("/Host: (.*)\r\n/", $buffer, $match)) { $h = $match[1]; } if (preg_match("/Origin: (.*)\r\n/", $buffer, $match)) { $o = $match[1]; } if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $buffer, $match)) { $key = $match[1]; } return [$r, $h, $o, $key]; } //验证socket function calcKey($key) { $accept = base64_encode(sha1($key . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true)); return $accept; } //解码数据(解析client发送的数据) function unmask($text) { $length = ord($text[1]) & 127; if ($length == 126) { $masks = substr($text, 4, 4); $data = substr($text, 8); } elseif ($length == 127) { $masks = substr($text, 10, 4); $data = substr($text, 14); } else { $masks = substr($text, 2, 4); $data = substr($text, 6); } $text = ""; for ($i = 0; $i < strlen($data); ++$i) { $text .= $data[$i] ^ $masks[$i % 4]; } return $text; } //编码数据(编码向client发送的数据) function mask($text) { $b1 = 0x80 | (0x1 & 0x0f); $length = strlen($text); if ($length <= 125) $header = pack('CC', $b1, $length); elseif ($length > 125 && $length < 65536) $header = pack('CCn', $b1, 126, $length); elseif ($length >= 65536) $header = pack('CCNN', $b1, 127, $length); return $header . $text; } socket_close($sock); ?>
(2).Javascript客户端
<script type="text/javascript"> if("WebSocket" in window) { var ws = new WebSocket("ws://127.0.0.1:6936"); //socket握手自动触发推送消息 ws.onopen = function() { var data = { id: 287, name: '某终端' } data = JSON.stringify(data); ws.send(data); }; //监听来自服务端的消息 ws.onmessage = function(evt) { console.log(evt.data); }; //客户端或服务端断开自动触发 ws.onclose = function() { console.log('websocket已经断开!'); }; } else { console.log('您的浏览器不支持h5,无法启动websocket'); } </script>
php调用Webservice基本语法如下:$url ='xxxxxxx.cn' //链接服务器端 $client = new SoapClient($url);通过以上语法已经连接到webservice,也可将wsdl在本地使用,...
在一个正式项目中操作人员提交239个产品信息进行保存,但是系统却提示没有提交239个产品,于是开启错误信息,显示如下:Warning: Unknown: Input variables exceeded 1000. To incr...
逛公众号文章看到文章"php实现事件监听与触发的方法,你用过吗?",我就好奇了,php又不是asp.net的webform,哪里来的服务端事件监听。于是学习了一波。先看下监听类:class Event { /** &nbs...
(1).学习的目标:学会创建父子进程,并且能够区分当前进程是父还是子;了解父进程执行过程,子进程执行过程;能够用多进程执行任务(2).相关函数学习: (2.1)pcntl_fork()执行时: &nbs...
(1).在PHP中可以查看的环境变量包括: (1.1).电脑环境变量 (2.1).服务器环境变量(2).getenv()函数获取一个环境变量的值.参数1是环境变量的key,参数2值为true的时候仅从你的电脑环境变量中查找,参数2值为false会从两种变量中全部查询//获取我电脑登录的用户名,输出A...
<?php /** * @throws Exception */ function curl() { throw new \Exception('err...