Websocket module

After installing and configuring according to the previous two chapters, you can create the required websocket module under app/WebSocket to handle the relevant logic.

Several events that are allowed to be processed by the user in each module are handshake open message close



@WsModule module class annotation tag @WsModule

  • Annotation class: Swoft\WebSocket\Server\Annotation\Mapping\WsModule
  • Scope: CLASS
  • Have attributes:
    • path string identifies the URI path that allows the ws connection.
    • controllers array is bound to the message controller class of this module
    • messageParser string is bound to the message data parser of this module
    • defaultOpcode integer The default message data opcode this module


 * @WsModule("/echo", controllers={XXController::class, XYController::class})

The above comment indicates the URI path that allows ws connections. That is, the ws connection requested by the client is similar: ws://IP:PORT/echo

Tip: You can bind multiple controllers, please note that the introduction of the complete controller, message parser class


Method annotation @OnHandshake tag handling handshake method

  • Annotation class: Swoft\WebSocket\Server\Annotation\Mapping\OnHandshake
  • Scope of action: METHOD

This method is optional. If there are no special requirements, you can ignore it and the framework will help you shake hands and respond to the handshake successfully.

Must return an array with two elements

  • The value of the first element of bool to decide whether to handshake
  • The second element is the response object - you can set some custom header, body and other information in the response


After the handshake is successful, the open event is triggered. The method annotations the @OnOpen tag corresponding method.

At this point you can send a message to the client :)

  • Annotation class: Swoft\WebSocket\Server\Annotation\Mapping\OnOpen
  • Scope of action: METHOD
  • This method is also optional and can be


The method annotations @OnMessage mark a message processing method.

At this stage you can receive the client's message and send a message to the other party.

  • Annotation class: Swoft\WebSocket\Server\Annotation\Mapping\OnMessage
  • Scope of action: METHOD
  • When you are not bound to a message controller, it means that you want to handle the logic of the message phase yourself. This method must exist .
  • When you have a bound message controller, the framework automatically parses the message and routes it to the specified message processing method.


The method annotation @OnClose marks the processing method when closing the connection.

This event is fired when the client closes the connection or the server actively closes the connection elsewhere.

You can do some work after the connection is closed, such as logging logs, unbinding users, etc...

  • Annotation class: Swoft\WebSocket\Server\Annotation\Mapping\OnClose
  • Scope of action: METHOD
  • This method is also optional and can be

Note: The connection has been closed when this event is triggered and no more messages can be sent to the other party.

Quickly create module classes

You can use the swoftcli tool to quickly create a websocket module class:

  • The default generated module class that supports built-in routing scheduling
 php swoftcli.phar gen:wsmod chat --prefix /chat 
  • Generate a module class for user-defined scheduling
 php swoftcli.phar gen:wsmod chat --prefix /chat --tpl-file ws-module-user 

Code example

  • The server object on this method is an instance of Swoole\WebSocket\Server

namespace App\WebSocket;

use Swoft\Http\Message\Request;
use Swoft\Http\Message\Response;
use Swoft\WebSocket\Server\Annotation\Mapping\OnClose;
use Swoft\WebSocket\Server\Annotation\Mapping\OnHandshake;
use Swoft\WebSocket\Server\Annotation\Mapping\OnOpen;
use Swoft\WebSocket\Server\Annotation\Mapping\OnMessage;
use Swoft\WebSocket\Server\Annotation\Mapping\WsModule;
use Swoole\WebSocket\Frame;
use Swoole\WebSocket\Server;

 * Class EchoModule
 * @WsModule("/echo")
class EchoModule
     * 在这里你可以验证握手的请求信息
     * @OnHandshake()
     * @param Request $request
     * @param Response $response
     * @return array [bool, $response]
    public function checkHandshake(Request $request, Response $response): array
        return [true, $response];

     * On connection has open
     * @OnOpen()
     * @param Request $request
     * @param int     $fd
    public function onOpen(Request $request, int $fd): void
        server()->push($fd, 'hello, welcome! :)');

     * @OnMessage()
     * @param Server $server
     * @param Frame $frame
    public function onMessage(Server $server, Frame $frame)
        $server->push($frame->fd, 'I have received message: ' . $frame->data);

     * On connection closed
     * - you can do something. eg. record log
     * @OnClose()
     * @param Server $server
     * @param int    $fd
    public function onClose(Server $server, int $fd): void
        // you can do something. eg. record log, unbind user...

Client code

Easy client js code example

 // wsUrl = websocket host + module path
const wsUrl = 'ws://'
let ws = new WebSocket(wsUrl)

ws.onerror = function (event){
    console.log("error: " + event.data)

ws.onopen = function (event){
    console.log("open: connection opened");

ws.onmessage = function (event){
    console.log("message: " + event.data);

ws.onclose = function (event){
    console.log("close: connection closed")

Client test

If you have devtool installed and enabled, you can open the page IP:PORT/__devtool/ws/test for ws testing.

  • Fill in your ws server address (be careful not to forget the URI path) ( 2.0 devtool no web UI )
  • Then you can connect to the ws server and send and receive messages.
  • If you run the server in the foreground, you can also see the ws connection and message log on the console running the server.

Here we use http://www.websocket.org/echo.html simple test using

 // wsUrl = websocket host + module path
var wsUrl = 'ws://' 


Of course, you can also find a ws test page on the Internet to test. Note that make sure the server is up and the address is not filled incorrectly.