> For the complete documentation index, see [llms.txt](https://xiaoxiami.gitbook.io/swoole/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://xiaoxiami.gitbook.io/swoole/swoole-ji-chu/wang-luo-tong-xin-yin-qing/chuang-jian-websocket-fu-wu.md).

# 创建websocket服务器

建议先阅读官方文档[WebSocket\Server](https://wiki.swoole.com/wiki/page/397.html)章节

* 一、websocket介绍
* 二、Swoole\_websocket简介
* 三、websoket服务创建

## 一、websocket介绍

**1、websocket是什么呢？**&#x20;

websocket是一个协议，它仅仅就是一个协议而已，跟我们所了解的http协议、https协议、ftp协议等等一样，都是一种单纯的协议。

**2、websocket的特点呢？**&#x20;

相对于Http这种非持久连接而言，websocket协议是一种持久化连接，它是一种独立的，**基于TCP的协议**。基于websocket，我们可以实现客户端和服务端双向通信。

在websocket出现之前，为了解决此类问题，常用的解决方法有轮询和long pull,这两种技术都是客户端和服务端建立源源不断的HTTP连接，非常消耗带宽和服务器资源。

websocket是双向持久连接，客户端和服务端只需要第一次建立连接即可实现双向通信。

> **列出WebSocket特点：**
>
> * 建立在TCP协议
> * 性能开销小通信高效
> * 客户端可以与任意服务器通信
> * 协议标识符ws wss
> * 持久化网络通信协议（长连接）

## 二、Swoole\_websocket简介

* Swoole增加了内置的WebSocket服务器支持，通过几行PHP代码就可以写出一个异步非阻塞多进程的WebSocket服务器。

![](/files/-LfnTG0y05vXCVHOUyXd)

* 1、websocket\_server是在swoole\_http\_server基础之上做了协议解析
* 2、完整的websocket协议会封装在frame对象当中

三、websoket服务创建

简单示例：

![](/files/-LfnTG109Mxf3PEQdxHS)

```php
<?php

$server = new swoole_websocket_server("0.0.0.0", 8812);

//监听websocket连接打开事件
$server->on('open', 'onOpen');
function onOpen($server, $request) {
    print_r($request->fd);
}

// 监听ws消息事件
$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";
    $server->push($frame->fd, "singwa-push-secesss");
});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();
```

**onOpen**

```php
function onOpen(swoole_websocket_server $svr, swoole_http_request $req);
```

* WebSocket客户端与服务器建立连接并完成握手后会回调此函数。
* $req 是一个Http请求对象，包含了客户端发来的握手请求信息
* onOpen事件函数中可以调用push向客户端发送数据或者调用close关闭连接
* onOpen事件回调是可选的

**onMessage**

当服务器收到来自客户端的数据帧时会回调此函数。

```php
function onMessage(swoole_websocket_server  $server, swoole_websocket_frame $frame)
```

* $frame 是swoole\_websocket\_frame对象，包含了客户端发来的数据帧信息
* onMessage回调必须被设置，未设置服务器将无法启动

$frame

$frame 共有4个属性，分别是:

* $frame->fd，客户端的socket\_id，使用$server->push推送数据时需要用到。
* $frame->data，数据内容，可以是文本内容也可以是二进制数据，可以通过opcode的值来判断
* $frame->opcode，WebSocket的OpCode类型，可以参考WebSocket协议标准文档
* $frame->finish， 表示数据帧是否完整，一个WebSocket请求可能会分成多个数据帧进行发送

**Push方法**

```php
function WebSocket\Server->push(int $fd, $data, int $opcode = 1, bool $finish = true);
```

$fd 客户端连接的ID，如果指定的$fd对应的TCP连接并非websocket客户端，将会发送失败

$data 要发送的数据内容向websocket客户端连接推送数据，长度最大不得超过2M。

$data 如果是文本类型，编码格式必然是UTF-8，这是WebSocket协议规定的

$opcode，指定发送数据内容的格式，默认为文本。发送其它格式可以参考文档常量

**注意：**

1、连接保持+心跳

Websocket也是长连接的形式，同样支持自己实现心跳包的检测

2、校验客户端连接的有效性

我们创建的websocket\_server,是对外开放的，也就是任何人都能连接过来，对于非websocket协议同样能触发，所以我们要判断当前是websocket客户端并且能够通讯才进行发送。

根据以上注意的两点，示例：

```php
<?php

$server=new swoole\websocket\server('0.0.0.0',9500);

$server->set([
      'heartbeat_idle_time'=>30,
      'heartbeat_check_interval'=>10,
    ]
);
$server->on('open', function (swoole_websocket_server $server, $request) {
    //var_dump($request);
    echo "server: handshake success with fd{$request->fd}\n";


});


$server->on('message', function (swoole_websocket_server $server, $frame) {
    echo "receive from {$frame->fd}:{$frame->data},opcode:{$frame->opcode},fin:{$frame->finish}\n";

    //得到所有连接的客户端
   //var_dump($server->getClientList(0, 10));

    //消息广播
    sleep(3);
    foreach ($server->connection_list() as $fd ){

         //检测websocket客户端是否有效
        if($server->exist($fd)){
            //发送给客户端
            //$server->push($fd, "receive from {$fd}的消息");
            $server->push($fd, "receive from {$fd}的消息",2);
        }else{
            $server->close($fd); //关闭掉指定客户端
        }
    }
});

$server->on('receive', function ($server, $fd, $from_id, $data) {
        var_dump($data);
});

$server->on('close', function ($ser, $fd) {
    echo "client {$fd} closed\n";
});

$server->start();
```

websocket client端的代码：

```markup
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<script>

    ws = new WebSocket('ws://218.64.129.244:9500');

    ws.onopen = function(){
        ws.send('内容');
        console.log("已经打开了websocket连接，可以进行实时通信了");
    };

    ws.onmessage = function(e){
        console.log("接受到来自服务器端的数据:"+e.data);
    }

    ws.onerror=function (e) {
        console.log("连接失败");
    }


</script>
</body>
</html>
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://xiaoxiami.gitbook.io/swoole/swoole-ji-chu/wang-luo-tong-xin-yin-qing/chuang-jian-websocket-fu-wu.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
