• webrtc学习--websocket服务器


    websocket服务器

    前言

    推荐一个零声学院免费教程,个人觉得老师讲得不错,
    分享给大家:[Linux,Nginx,ZeroMQ,MySQL,Redis,
    fastdfs,MongoDB,ZK,流媒体,CDN,P2P,K8S,Docker,
    TCP/IP,协程,DPDK等技术内容,点击立即学习:

    websocket服务器,使用asio和websocketpp库
    asio库:asio-1.22.1
    websocketpp库:websocketpp-0.8.2

    asio下载地址:https://sourceforge.net/projects/asio/files/asio/
    websocketpp-0.8.2下载地址:https://github.com/zaphoyd/websocketpp/tree/0.8.2

    1. websocket 服务器使用asio和websocketpp做服务器。这样只要使用头文件就可以了。
    2. asio作为网络库

    asio库支持TCP、UDP和ICMP通信协议,在名字空间asio::ip中提供大量网络通信方面的函数和类

    1. websocketpp 摘自websocketpp官网(https://docs.websocketpp.org/index.html

    WebSocket++ 是一个 C++ 库,可用于实现 WebSocket 功能。该项目的目标是提供可移植、灵活、轻量级、低级和高性能的 WebSocket 实现。WebSocket++ 不打算单独用作 Web 应用程序框架或功能齐全的 Web 服务平台。因此,组件、示例和性能调整都适合作为 WebSocket 客户端或服务器运行。有一些与此无关的最小便利功能(例如响应 WebSocket 升级以外的 HTTP 请求的能力),但这些不是项目的重点。特别是 WebSocket++ 不打算实现任何与 WebSocket 无关的回退选项(ajax / long polling / comet / etc)。为了保持紧凑并提高可移植性,WebSocket++ 项目努力在可能和适当的情况下减少或消除外部依赖。WebSocket++ 核心除了 C++11 标准库之外没有其他依赖项。对于非 C++11 编译器,Boost 库为使用的 C++11 功能提供了一些 polyfill。WebSocket++ 实现了一个可插拔的数据传输组件。默认组件允许通过使用 STL iostream 或通过读取和写入 char 缓冲区的原始字节混洗来减少功能。该组件没有非 STL 依赖,可以在没有 Boost 的 C++11 环境中使用。还包括一个基于 Asio 的传输组件,它提供了全功能的网络客户端/服务器功能。该组件需要 Boost Asio 或 C++11 编译器和独立的 Asio。作为一个高级选项,如果您想使用其他库提供自己的传输层,WebSocket++ 支持自定义传输层。
    为了适应 WebSocket++ 收集的各种用例,该库的构建方式使大多数主要组件都是松散耦合的,并且可以换出和替换。WebSocket++ 将尝试跟踪 WebSocket 协议的未来发展以及开发中的任何扩展。

    准备

    windows下添加宏,只需要asio,不需要boost

    asio 不使用boost

    CMakeLists.txt

    IF(WIN32)
    ADD_DEFINITIONS(-DWIN32_LEAN_ADN_MEAN)
    ADD_DEFINITIONS(-DWIN32)
    ENDIF(WIN32)
    ADD_DEFINITIONS(-DASIO_STANDALONE)
    ADD_DEFINITIONS(-D_WEBSOCKETPP_CPP11_INTERNAL_)
    ADD_DEFINITIONS(-D_WEBSOCKETPP_CPP11_TYPE_TRAITS_)
    ADD_DEFINITIONS(-D_WEBSOCKETPP_DEFAULT_DELETE_FUNCTIONS_)
    ADD_DEFINITIONS(-D_WEBSOCKETPP_MOVE_SEMANTICS_)
    ADD_DEFINITIONS(-DASIO_HAS_STD_SYSTEM_ERROR)
    #ADD_DEFINITIONS(-D_SCL_SECURE_NO_WARNINGS)
    ADD_DEFINITIONS(-DASIO_HAS_MOVE)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    asio和websocketpp实现简单的websocket服务器

    server.h

    #ifndef _SERVER_H_
    #define _SERVER_H_
    
    #include 
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    #include "session.h"
    
    typedef websocketpp::server websocket_server;
    using websocketpp::connection_hdl;
    using websocketpp::lib::placeholders::_1;
    using websocketpp::lib::placeholders::_2;
    using websocketpp::lib::bind;
    
    
    class Server
    {
    public:
        Server() = delete;
        Server(Server& server) = delete;
        Server operator=(Server& server) = delete;
    
        Server(asio::io_context& io_service, uint16_t port);
    
        websocket_server* GetServer() { return &_server; }
    
        void Start();
        void Stop();
        std::shared_ptr& GetSessionFromhdl(connection_hdl hdl);
        void onOpen(connection_hdl);
        void onClose(connection_hdl);
        void onMessage(connection_hdl, websocket_server::message_ptr);
    
    private:
        websocket_server    _server;
        connection_hdl      _hdl;
        std::map, std::owner_less> _mapClients;
        asio::io_context& _io_service;
    
        uint16_t _iPort;
        std::function _openCb;
        std::function _closeCb;
        std::function _messageCb;
    
    };
    
    #endif
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54

    server.cpp

    #include "server.h"
    #include 
    
    Server::Server(asio::io_context& io_service, uint16_t port)
        : _iPort(port)
        , _io_service(io_service)
    {
        _server.init_asio(&io_service);
        _server.set_reuse_addr(true);
        _server.set_open_handler(std::bind(&Server::onOpen, this, ::_1));
        _server.set_close_handler(std::bind(&Server::onClose, this, ::_1));
        _server.set_message_handler(std::bind(&Server::onMessage, this, ::_1, ::_2));
    }
    
    void Server::Start()
    {
        _server.listen(_iPort);
        _server.start_accept();
    }
    
    void Server::Stop()
    {
        _server.stop();
    }
    
    std::shared_ptr& Server::GetSessionFromhdl(connection_hdl hdl)
    {
        auto iter = _mapClients.find(hdl);
        if (iter == _mapClients.end()) {
            throw std::invalid_argument("No data available for session");
        }
        return iter->second;
    }
    
    void Server::onOpen(connection_hdl hdl)
    {
        auto iter = _mapClients.find(hdl);
        if (iter == _mapClients.end()) {
            auto client = std::make_shared(_io_service, this, hdl);
            _mapClients.insert(std::make_pair(hdl, client));
            client->onOpen();
        }
        else
        {
            return;
        }
    }
    
    void Server::onClose(connection_hdl hdl)
    {
        auto ptr = GetSessionFromhdl(hdl);
        ptr->onClose();
    }
    
    void Server::onMessage(connection_hdl hdl, websocket_server::message_ptr msg)
    {
        auto ptr = GetSessionFromhdl(hdl);
        ptr->onMessage(msg);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59

    session.h

    #ifndef _SESSION_H_
    #define _SESSION_H_
    
    #include 
    #include 
    #include 
    
    #include 
    #include 
    #include 
    #include 
    
    #include 
    #include 
    
    typedef websocketpp::server websocket_server;
    using websocketpp::connection_hdl;
    using websocketpp::lib::placeholders::_1;
    using websocketpp::lib::placeholders::_2;
    using websocketpp::lib::bind;
    class Server;
    
    class Session : public std::enable_shared_from_this
    {
    public:
        Session(asio::io_context& io_service, Server* server, connection_hdl hdl);
        void onOpen();
        void onClose();
        void onMessage(websocket_server::message_ptr msg);
        void send(std::string& str);
        void taskInLoop(std::function func);
    
    private:
        connection_hdl _hdl;
        Server* _server;
        asio::io_context& _io_service;
    
    };
    
    #endif // _SESSION_H_
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    session.cpp

    #include "server.h"
    #include "session.h"
    
    Session::Session(asio::io_context& io_service, Server* server, connection_hdl hdl)
        : _server(server)
        , _io_service(io_service)
        , _hdl(hdl)
    {
    
    }
    void Session::onOpen()
    {
        websocket_server::connection_ptr conn = _server->GetServer()->get_con_from_hdl(_hdl);
        std::cout << conn->get_uri()->str()  << " : " << conn->get_resource() << " - " << conn->get_remote_endpoint() << std::endl;
    }
    void Session::onClose()
    {
    
    }
    
    void Session::onMessage(websocket_server::message_ptr msg)
    {
        std::string str = msg->get_payload();
        std::cout << "msg: " << str << std::endl;
    }
    
    void Session::send(std::string& str)
    {
        _server->GetServer()->send(_hdl, str, websocketpp::frame::opcode::text);
    }
    
    void Session::taskInLoop(std::function func)
    {
        _io_service.post(func);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35

    main.cpp

    #include "server.h"
    
    int main()
    {
        asio::io_context io;
        Server server(io, 9000);
        server.Start();
        io.run();
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    websocket 服务器测试

    websocket测试地址:
    http://www.jsons.cn/websocket/
    http://www.websocket-test.com/

    websocket 服务器

    在这里插入图片描述

    websocket 测试服务器代码

    代码下载

    参考链接

    https://github.com/zhangkai1234/webassembly-ffmpeg

  • 相关阅读:
    Java多线程(二) 线程池
    “简单”的无限魔方
    自制操作系统日志——第二十七天
    COOKIE和SESSION及案例
    linux chrdev字符设备驱动程序示例
    终极大招~pycharm自动补全opencv代码提示功能
    【案例实战】SpringBoot整合阿里云文件上传OSS
    Node.js入门 | 青训营笔记
    pandas是什么以及pandas的三种数据结构Series、DataFrame、MultiIndex的创建方式函数代码
    RKMPP库快速上手--(一)RKMPP功能及使用详解
  • 原文地址:https://blog.csdn.net/qq_18286031/article/details/126001264