0 CHN 04 3 控制器 WebSocketController
Nitromelon edited this page 2024-05-13 15:09:34 +08:00
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

English | 简体中文

顾名思义,WebSocketController用于处理websocket逻辑。websocket是基于HTTP的一种长连接方案在websocket建立之初有一次HTTP格式的请求和应答交换建立完成后所有的消息在websocket上传输消息由固定的格式包装但消息的内容和收发次序没有任何要求完全由用户定义。

生成

可以由drogon_ctl工具快速生成WebSocketController的源文件,命令格式如下:

drogon_ctl create controller -w <[namespace::]class_name>

假设我们要通过websocket实现一个简单的回声功能即服务端只是简单的把客户端发来的消息再发回去通过drogon_ctl创建WebSocketController的实现类EchoWebsock如下

drogon_ctl create controller -w EchoWebsock

该命令会生成EchoWebsock.h和EchoWebsock.cc两个文件

//EchoWebsock.h
#pragma once
#include <drogon/WebSocketController.h>
using namespace drogon;
class EchoWebsock:public drogon::WebSocketController<EchoWebsock>
{
  public:
    void handleNewMessage(const WebSocketConnectionPtr&,
                          std::string &&,
                          const WebSocketMessageType &) override;
    void handleNewConnection(const HttpRequestPtr &,
                             const WebSocketConnectionPtr&) override;
    void handleConnectionClosed(const WebSocketConnectionPtr&) override;
    WS_PATH_LIST_BEGIN
    //list path definitions here;
    WS_PATH_LIST_END
};
#include "EchoWebsock.h"
void EchoWebsock::handleNewMessage(const WebSocketConnectionPtr &wsConnPtr,std::string &&message)
{
    //write your application logic here
}
void EchoWebsock::handleNewConnection(const HttpRequestPtr &req,const WebSocketConnectionPtr &wsConnPtr)
{
    //write your application logic here
}
void EchoWebsock::handleConnectionClosed(const WebSocketConnectionPtr &wsConnPtr)
{
    //write your application logic here
}

使用

  • 路径映射

    编辑后内容如下:

    //EchoWebsock.h
    #pragma once
    #include <drogon/WebSocketController.h>
    using namespace drogon;
    class EchoWebsock:public drogon::WebSocketController<EchoWebsock>
    {
    public:
        virtual void handleNewMessage(const WebSocketConnectionPtr&,
                                    std::string &&,
                                    const WebSocketMessageType &)override;
        virtual void handleNewConnection(const HttpRequestPtr &,
                                        const WebSocketConnectionPtr&)override;
        virtual void handleConnectionClosed(const WebSocketConnectionPtr&)override;
        WS_PATH_LIST_BEGIN
        //list path definitions here;
        WS_PATH_ADD("/echo");
        WS_PATH_LIST_END
    };
    
    //EchoWebsock.cc
    #include "EchoWebsock.h"
    void EchoWebsock::handleNewMessage(const WebSocketConnectionPtr &wsConnPtr,std::string &&message)
    {
        //write your application logic here
        wsConnPtr->send(message);
    }
    void EchoWebsock::handleNewConnection(const HttpRequestPtr &req,const WebSocketConnectionPtr &wsConnPtr)
    {
        //write your application logic here
    }
    void EchoWebsock::handleConnectionClosed(const WebSocketConnectionPtr &wsConnPtr)
    {
        //write your application logic here
    }
    

    首先,在这个例子中,通过WS_PATH_ADD宏把这个控制器注册到了/echo路径上,WS_PATH_ADD宏的用法跟之前介绍的其他控制器的宏类似,也可以注册路径并且附带若干中间件和过滤器。由于websocket在框架中单独处理所以它可以和前两种控制器的路径重复而不会相互影响。

    其次本例中三个虚函数的实现只有handleNewMessage有实质内容只是简单的把收到的消息通过send接口发回客户端。把这个控制器编译进框架就可以看到效果请各位自己试验吧。

    注意和通常的HTTP协议一样http的websocket可以被旁路还原如果需要安全保障应由https提供加密功能当然用户自己在服务端和客户端完成加密和解密也是可以的只是https更方便底层都由drogon处理用户只需关心业务逻辑。

    用户自定义的WebSocketController类继承自drogon::WebSocketController类模板模板参数是子类类型用户需自己实现如下三个虚函数来对websocket的建立、关闭和消息进行处理

    virtual void handleNewConnection(const HttpRequestPtr &req,const WebSocketConnectionPtr &wsConn);
    virtual void handleNewMessage(const WebSocketConnectionPtr &wsConn,std::string &&message,
    const WebSocketMessageType &);
    virtual void handleConnectionClosed(const WebSocketConnectionPtr &wsConn);
    

    容易知道:

    • handleNewConnection在websocket建立之后被调用req是客户端发来的建立请求这时候框架已经返回了response用户可以做的是通过req获得一些额外信息比如token之类。wsConn是这个websocket对象的智能指针常用的接口后面再谈。
    • handleNewMessage在websocket收到新的消息之后被调用消息存储在message变量里注意这个message是完整的消息净荷框架已经做完了消息的解封包和解码等工作用户直接处理消息本身即可。
    • handleConnectionClosed在websocket连接关闭之后调用用户可以做一些收尾工作。
  • 接口

    WebSocketConnection对象常用接口如下

    //发送websocket消息消息的编码和封包都由框架负责这里直接发送消息的净荷
    void send(const char *msg,uint64_t len);
    void send(const std::string &msg);
    
    //本websocket的本端和远端地址
    const trantor::InetAddress &localAddr() const;
    const trantor::InetAddress &peerAddr() const;
    
    //本weosocket的连接状态
    bool connected() const;
    bool disconnected() const;
    
    //关闭本websocket
    void shutdown();//close write
    void forceClose();//close
    
    //设置和获取本websocket的上下文由用户存入一些业务数据
    //any类型意味着可以存取任意类型的对象。
    void setContext(const any &context);
    const any &getContext() const;
    any *getMutableContext();
    

05 中间件和过滤器