PHP创建websocket服务端

创建这个服务端需要先开启sockets扩展,没有开启的话,无论如何都会报错

只需要在php.ini文件中找到sockets扩展并将其前面的分号删除能将其开启

开启前:

;extension=sockets

开启后:

extension=sockets

开启完毕,接下来我们就可以进入正题了;首先,我们了解几个函数:

socket_create(AF_INET, SOCK_STREAM, SOL_TCP);//用于创建套接字

socket_bind( $this->master,$ip,$port);//用于绑定ip和端口

socket_listen( $this->master,1000);//用于调用connect连接的套接字和监听相关端口

socket_accept($this->master);//负责握手连接

socket_recv($socket, $buffer, 1024, 0);//从已连接的socket(客户端)接收数据

socket_write($socket,$upgrade,strlen($upgrade));//给单独客户端发送数据

send($message)//发送数据

socket_close($socket);//断开连接

很多步骤和PHP创建socket差不多,

不同主要在于socket_write使用和数据需要解、封帧,我们需要将http升级为websocket

http升级为websocket

if(preg_match("/Sec-WebSocket-Key: (.*)\r\n/",$buffer,$match)){
        	$responseKey=base64_encode(sha1($match[1] . '258EAFA5-E914-47DA-95CA-C5AB0DC85B11',true));
        	$upgrade="HTTP/1.1 101 Switching Protocol\r\n".
        	         "Upgrade: websocket\r\n".
        	         "Connection: Upgrade\r\n".
        	         "Sec-WebSocket-Accept:".$responseKey."\r\n\r\n";
        	         socket_write($socket,$upgrade,strlen($upgrade));
        }

$socket是我们创建的连接,$buffer是客户端第一次连接时发送的数据

注意:Sec-WebSocket-Key: (.*)//括号和冒号之间是要有空格的

解帧

        $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;

$buffer是客户端第一次连接时发送的数据

封帧

        $len=strlen($message);
		if($len<=125){
			return "\x81".chr($len).$message;
		}else if($len<=65535){
			return "\x81".chr(126).pack("n",$len).$message;
		}else{
			return "\x81".chr(127).pack("xxxxN",$len).$message;
		}

$message是我们需要发送的数据

前端连接前记得运行服务端,运行方式:

在cmd输入

php 你的服务端PHP文件路径

运行前先配置环境变量:将你的PHP安装路径添加到Path中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
对于 Hyperf WebSocket 服务端的鉴权,你可以在 onHandShake 方法中进行实现,该方法会在 WebSocket 握手阶段触发。具体实现步骤如下: 1. 在 config/autoload 文件夹下创建一个 auth.php 配置文件,用于存储需要鉴权的用户信息。例如: ``` <?php return [ 'users' => [ [ 'username' => 'user1', 'password' => 'password1', ], [ 'username' => 'user2', 'password' => 'password2', ], ], ]; ``` 2. 在 WebSocket 控制器的 onHandShake 方法中获取客户端发送的参数(如用户名和密码),并与 auth.php 中存储的用户信息进行比对。如果验证通过,则保存用户信息到 WebSocket 的上下文中,以便后续操作使用。例如: ``` <?php declare(strict_types=1); namespace App\Controller; use Hyperf\WebSocketServer\Context; use Hyperf\WebSocketServer\Sender; use Hyperf\WebSocketServer\Annotation\WebSocket; use Hyperf\WebSocketServer\Contract\RequestInterface; use Hyperf\WebSocketServer\Contract\ResponseInterface; /** * @WebSocket */ class AuthController { public function onHandShake(RequestInterface $request, ResponseInterface $response): void { $username = $request->get('username'); $password = $request->get('password'); // 从配置文件中获取用户信息 $users = config('auth.users', []); // 验证用户信息 foreach ($users as $user) { if ($user['username'] === $username && $user['password'] === $password) { // 验证通过,保存用户信息到上下文中 Context::set('user', $user); return; } } // 验证失败,关闭 WebSocket 连接 $sender = make(Sender::class, ['response' => $response]); $sender->close(); } } ``` 3. 在其他 WebSocket 控制器的方法中,可以通过 Context::get('user') 获取已经鉴权的用户信息,进行后续操作。例如: ``` <?php declare(strict_types=1); namespace App\Controller; use Hyperf\Di\Annotation\Inject; use Hyperf\WebSocketServer\Context; use Hyperf\WebSocketServer\Annotation\WebSocket; /** * @WebSocket */ class ChatController { /** * @Inject * @var \Hyperf\WebSocketServer\Sender */ protected $sender; public function onMessage($fd, $data) { $user = Context::get('user'); if (! $user) { // 用户未鉴权,无法进行操作 return; } // 用户已鉴权,进行后续操作 // ... } } ``` 通过以上步骤,你就可以在 Hyperf WebSocket 服务端实现用户鉴权。当然,具体实现方式可以根据自己的业务需求进行调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

知勤者笔记

给点吧,没动力了!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值