当前位置:网站首页>socket+websocket
socket+websocket
2022-07-29 11:31:00 【minihuabei】
<?php
error_reporting(E_ALL ^ E_NOTICE);
/* Allow the script to hang around waiting for connections. */
set_time_limit(0);
/* Turn on implicit output flushing so we see what we're getting * as it comes in. */ ob_implicit_flush();// 直接输出到浏览器 $address = '192.168.0.171'; const MAX_LISTEN_NUM = 200; $port = 1212; $socketPool = []; if (($hostSocket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP)) === false) { echo "socket_create() failed: reason: " . socket_strerror(socket_last_error()) . "\n"; } // 设置TIME_WAIT状态socket可以复用 socket_set_option($hostSocket, SOL_SOCKET, SO_REUSEADDR,1); // 强制关闭socket开关:l_linger=0开启,1平滑关闭 $linger = array ('l_linger' => 0, 'l_onoff' => 1); socket_set_option($hostSocket, SOL_SOCKET, SO_LINGER, $linger); if (socket_bind($hostSocket, $address, $port) === false) { echo "socket_bind() failed: reason: " . socket_strerror(socket_last_error($hostSocket)) . "\n"; } if (socket_listen($hostSocket, 200) === false) { echo "socket_listen() failed: reason: " . socket_strerror(socket_last_error($hostSocket)) . "\n"; } // 把所有socket存储在$sockets $socketPool[] = ['source'=>$hostSocket]; try { while(true){ $sockets = array_column($socketPool,'source'); // 拷贝clients $write = null; // 可读socket $except = null; // 异常socket $readNum = socket_select($sockets,$write,$except,null); foreach ($sockets as $socket) { if ($socket == $hostSocket) { // 处理连接情况 $client = socket_accept($hostSocket); echo 'client:'.$client; echo 'client:'.(int)$client; if ($client < 0) { echo "socket_accept() failed: reason: " . socket_strerror(socket_last_error($hostSocket)) . "\n"; } else { $socketPool[(int)$client] = ['source'=>$client,'handshake'=>false]; } } else { $len = socket_recv($socket, $buff, 2048,0); echo 'len:'.$len; echo 'buff:'.$buff; $recvMsg = decode($buff); echo 'recvMsg:'.$recvMsg; // buff=null 证明socket已经关闭 if ($buff == null) { socket_close($socket); unset($socketPool[(int)$socket]); break; }else if ($socketPool[(int)$socket]['handshake']) { // 发送消息 $answMsg = frame(json_encode(['code'=>0,'msg'=>$recvMsg,'data'=>[]])); $host = '';
$port = '';
// socket_getpeername($socket,$host,$port);
// echo 'host:'.$host;
// echo 'port:'.$port;
@socket_write($socket,$answMsg,strlen($answMsg));
} else {
// 握手
$socketPool[(int)$socket]['handshake'] = true;
handshake($socket,$buff,$address,$port);
}
}
}
}
} catch (Exception $e) {
echo $e->getMessage();
socket_shutdown($hostSocket);
socket_close($hostSocket);
}
function handshake($socket,$buffer,$host, $port)
{
$headers = array();
$lines = preg_split("/\r\n/", $buffer);
foreach($lines as $line)
{
$line = rtrim($line);
if(preg_match('/\A(\S+): (.*)\z/', $line, $matches)){
$headers[$matches[1]] = $matches[2];
}
}
$secKey = $headers['Sec-WebSocket-Key'];
$secAccept = base64_encode(pack('H*', sha1($secKey . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11')));
//hand shaking header
$upgrade = "HTTP/1.1 101 Web Socket Protocol Handshake\r\n" .
"Upgrade: websocket\r\n" .
"Connection: Upgrade\r\n" .
"WebSocket-Origin: $host\r\n" .
"WebSocket-Location: ws://$host:$port\r\n".
"Sec-WebSocket-Version: 13\r\n" .
"Sec-WebSocket-Accept:$secAccept\r\n\r\n";
socket_write($socket, $upgrade);
}
// 解析数据帧
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;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<input type="text" name="msg" value="这是发送消息" id="msg"/><br>
<button onclick="send()">发送</button><br>
<button onclick="closeWs()">关闭连接</button>
<script>
var ws = new WebSocket('ws://192.168.0.171:1212/');
ws.onopen = function(e){
console.log("Connection open ...");
ws.send("发送消息");
}
ws.onmessage = function(e){
console.log("onmessage",e.data);
}
ws.onclose = function(e){
ws = null;
}
function closeWs(){
console.log('close ws');
ws.close();
}
function send(){
console.log('send');
var msg = document.getElementById('msg').value;
console.log('msg',msg);
ws.send(msg);
}
</script>
</body>
</html>
边栏推荐
- Paddlelite compilation and code running through the disk
- How to use grep to find pattern matching across multiple lines
- HMS Core Discovery第16期回顾|与虎墩一起,玩转AI新“声”态
- golang 实现文件上传下载
- 1.MySQL数据库的介绍
- Alluxio为Presto赋能跨云的自助服务能力
- Sunwenlong, Secretary General of the open atom open source foundation, worked together to expand open source
- Hugo NexT V4 介绍
- Great golang Road
- 593. 有效的正方形
猜你喜欢
MyCat中间件高可用、读写分离、分片、主从切换、ER分片
TCP and UDP
Zhou Hongyi: 360 is the largest secure big data company in the world
PyQt5快速开发与实战 6.6 QFormLayout(表单布局) && 6.7 嵌套布局 && 6.8 QSplitter
【无标题】
基于flask写的一个小商城mall项目
2022最新 wifi大师小程序独立版3.0.8
std::vector 拷贝、追加、嵌套访问
Niuke net brush questions
HMS Core音频编辑服务音源分离与空间音频渲染,助力快速进入3D音频的世界
随机推荐
AMH6.X升级到AMH7.0后,登录后台提示MySQL连接出错怎么解决?
DNS协议、ICMP协议、NAT技术
Watch the open source summit first | quick view of the sub Forum & Activity agenda on July 29
2022年企业直播行业发展洞察
IPv6 Foundation
fastjson使用方法
After connect and SQL join in on conditions and where
DOD and Dor, two artifacts to reduce "cognitive bias"
QWidget、QDialog、QMainWindow 的异同点
AI model risk assessment Part 2: core content
就这?TypeScript其实并不难!(建议收藏)
Why should kubernetes be used in development environments
GBase8s核心数据备份
开源峰会抢先看 | 7 月 29 日分论坛 & 活动议程速览
How to start writing helm charts for your kubernetes application
Talk about the establishment of performance testing environment
How to use grep to find pattern matching across multiple lines
Zhou Hongyi: 360 is the largest secure big data company in the world
北京大学公开课重磅来袭!欢迎走进「AI for Science」课堂
Collections.singletonList(T o)