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);
};

  

posted @ 2025-07-21 18:20  钢锅  阅读(31)  评论(0)    收藏  举报