PHP 原生配置WebSocket
PHP 原生配置WebSocket
PHP.INI开启
:extension=sockets =>>>>>> extension=sockets
<?php
// 初始化套接字 IPv4为AF_INET
$socket = socket_create(AF_INET6, SOCK_STREAM, SOL_TCP);
if ($socket === false) {
die("socket_create() failed: " . socket_strerror(socket_last_error()));
}
// 绑定端口 IPv4为 0.0.0.0
if (!socket_bind($socket, '::', 8080)) {
die("socket_bind() failed: " . socket_strerror(socket_last_error()));
}
// 开始监听
if (!socket_listen($socket, 5)) {
die("socket_listen() failed: " . socket_strerror(socket_last_error()));
}
echo "WebSocket server started on ws://localhost:8080\n";
// 主循环
while (true) {
$client = socket_accept($socket);
if ($client === false) continue;
// 握手处理
$request = socket_read($client, 5000);
if (preg_match("/Sec-WebSocket-Key: (.*)\r\n/", $request, $match)) {
$key = base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11', true));
$headers = "HTTP/1.1 101 Switching Protocols\r\n";
$headers .= "Upgrade: websocket\r\n";
$headers .= "Connection: Upgrade\r\n";
$headers .= "Sec-WebSocket-Accept: $key\r\n\r\n";
socket_write($client, $headers);
// 消息处理循环
while (true) {
$data = socket_read($client, 1024);
if ($data === false || strlen($data) < 2) break;
// 解码消息
$decoded = decodeFrame($data);
echo "控制台收到消息: $decoded\n";
if($decoded === 'PING'){
$decoded = '服务器心跳包,PONG';
}
// 编码并返回响应
$response = encodeFrame("服务器返回消息: $decoded");
socket_write($client, $response);
}
}
socket_close($client);
}
// 数据帧解码函数
function decodeFrame($buffer) {
$len = ord($buffer[1]) & 127;
$maskStart = ($len === 126) ? 4 : (($len === 127) ? 10 : 2);
$masks = substr($buffer, $maskStart, 4);
$data = substr($buffer, $maskStart + 4);
$decoded = '';
for ($i = 0; $i < strlen($data); ++$i) {
$decoded .= $data[$i] ^ $masks[$i % 4];
}
return $decoded;
}
// 数据帧编码函数
function encodeFrame($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);
} else {
$header = pack('CCNN', $b1, 127, $length);
}
return $header . $text;
}
浏览器控制台
// 创建WebSocket连接
const ws = new WebSocket("ws://api.zhouein.com:8080/wss/");
// 连接成功回调
ws.onopen = () => {
console.log("WebSocket连接已建立");
// 连接成功后发送测试消息
ws.send("Hello Server!");
};
// 接收消息回调
ws.onmessage = (e) => {
console.log("收到消息:", e.data);
};
// 错误处理
ws.onerror = (error) => {
console.error("WebSocket错误:", error);
};
// 关闭连接回调
ws.onclose = () => {
console.log("WebSocket连接已关闭");
};
// 发送消息函数
function sendMessage(msg) {
if (ws.readyState === WebSocket.OPEN) {
ws.send(msg);
} else {
console.warn("连接未就绪,无法发送消息");
}
}
// 关闭连接函数
function closeConnection() {
ws.close();
}
提供两个在线WS服务器
wss://2hangzhou.goeasy.io/socket.io/?EIO=3&transport=websocket&b64=1 wss://echo.websocket.org
在线测试地址
http://wstool.jackxiang.com/
https://www.bejson.com/httputil/websocket/
https://www.toolnb.com/tools/webSocketTools.html
https://tool.hibbba.com/websocket/
问题:
长江云,湖北电视直播, WebSocket 定时发送心跳包,Cookies 发送数据错误
let _this = this;
const ws = new WebSocket('wss://remote-wa.cjyun.org.cn/liveweb');
let lastActivityTime = new Date().getTime();
const heartbeatInterval = 10 * 1000;//60秒
//处理WebSocket连接状态
ws.onopen = function (event) {
console.log('Connectionopened:', event);
//先发送一次说明用户上线
ws.send(JSON.stringify({client_id: _this.client_id, aa_look: _this.aa_look, client_token: _this.client_token}));
console.log('WebSocketheartbeatfirst');
//定期发送心跳消息
setInterval(() => {
ws.send(JSON.stringify({
client_id: _this.client_id,
aa_look: _this.aa_look,
client_token: _this.client_token
}));
console.log('WebSocketheartbeatinterval');
}, heartbeatInterval);
};



该URL窗口F12调试, 控制台是正常发送数据.
其他的URL或在程序代码中, 连接WSS后, 发送一次数据将关闭.
//根据源代码, 模拟发送WebSocket 数据
//该代码在news.hbtv.com.cn域名下 F12调试正常发送数据;
//变更URL 只能发送一次, 关闭
const dataJson = {
aa_look: "6592298124554526",
client_id: "b71f5bb3-beff-4389-ac4b-2725e7d8ddb8",
client_token: "3LAU4Bluio8zyYrQRFCmpExwkNcEOrvM5_G7Z7Mzy-yni1ywnUGciM33-TTgWbykOcrc51b4yrEnIFNJ6vM7dkR055bvP6bJP2RjFqNmOpbL2LUOSNpWAgHUYDq-YfTO7ETxgkVgvvWH3Nea06gas8klgNPVTz3vuCjMi_gF6CM"
}
// WebSocket服务器地址
const wsUrl = 'wss://remote-wa.cjyun.org.cn/liveweb';
// 创建WebSocket连接
const ws = new WebSocket(wsUrl);
// 处理WebSocket连接状态
ws.onopen = function(event){
console.log('先发送一次说明用户上线Connection opened:', event);
console.log('ws:',ws);
console.log('event:',event);
// 先发送一次说明用户上线
ws.send(JSON.stringify(dataJson));
console.log('定期发送心跳消息WebSocket heartbeat first');
console.log('event:',event);
// 定期发送心跳消息
setInterval(() => {
ws.send(JSON.stringify(dataJson));
console.log('每10秒发送一次心跳WebSocket heartbeat interval');
console.log('ws:',ws);
console.log('event:',event);
}, 10000); // 每30秒发送一次心跳
};
ws.onmessage = function(event){
console.log('Received message: ', event.data);
console.log('ws:',ws);
console.log('event:',event);
};
ws.onclose = function(event){
console.log('尝试重新连接WebSocket is closed now.');
console.log('ws:',ws);
console.log('event:',event);
// 尝试重新连接
setTimeout(() => {
console.log('5秒后尝试重新连接Attempting to reconnect...');
ws = new WebSocket(wsUrl);
}, 5000); // 5秒后尝试重新连接
};
ws.onerror = function(error){
console.log('WebSocket error: ', error);
};

浙公网安备 33010602011771号