evpp库增加openssl和websocket支持

前言

evpp是一个基于libevent开发的现代化C++11高性能网络服务器,自带TCP/UDP/HTTP等协议的异步非阻塞式的服务器和客户端库。来自于奇虎360公司github,star: 2.7k。

使用方面,因为支持跨平台,通过vcpkg install evpp安装很方便,故在团队内推广,最近希望扩大其使用范围,奈何其不支持openssl和websocket,还需要自己动手。

本教程很多思路借鉴了 不败青铜: websocket协议实现及基于muduo库的功能扩展 https/ws/wss 的教程,因为evpp的设计学习自muduo,使得增加openssl的过程中非常顺利。

修改说明

本分支基于 evpp 8984ca6b

  • 增加build.md文档
  • 修改tcp_conn,SendInLoop(),HandleRead(),HandleWrite(),HandleClose()更改为虚函数以方便实现SslConn,WebSocketConn
  • 增加evpp/ssl目录,支持SSL over TCP,使用方法见evpp/ssl/ssl_server.h的类注释
  • 增加evpp/ws和evpp/sha1目录,支持WebSocket(ws协议),使用方法见evpp/ws/web_socket_server.h的类注释
    在这里插入图片描述

传送门:Github

使用

OpenSSL

详细代码参考:/evpp/examples/tls目录。

Server
#include <evpp/ssl/ssl_server.h>
#include <evpp/tcp_conn.h>

#ifdef WIN32
struct OnApp {
    OnApp() {
        // Initialize net work.
        WSADATA wsaData;
        // Initialize Winsock 2.2
        int nError = WSAStartup(MAKEWORD(2, 2), &wsaData);

        if (nError) {
            std::cout << "WSAStartup() failed with error: %d" << nError;
        }

    }
    ~OnApp() {
        system("pause");
    }
} __s_onexit_pause;
#endif

int main() {
    std::string addr = "0.0.0.0:8433";
    int thread_num = 4;
    evpp::EventLoop loop;

    if (!evpp::ssl::SSL_CTX_Init("google.com.pem", "google.com.key")) {
        LOG_ERROR << "SSL_CTX_Init error";
        return 0;
    }

    evpp::ssl::SSLServer server(&loop, addr, "TlsServer", thread_num, evpp::ssl::SSL_CTX_Get());
    server.SetMessageCallback([](const evpp::TCPConnPtr &conn,
                                 evpp::Buffer *msg) {
        LOG_INFO << "recv client msg:len=" << msg->length() << ",content=" << msg->ToString();
        // Do something with the received message
        conn->Send(msg); // At here, we just send the received message back.
    });
    server.SetConnectionCallback([](const evpp::TCPConnPtr &conn) {
        if (conn->IsConnected()) {
            LOG_INFO << "A new connection from " << conn->remote_addr();
        } else {
            LOG_INFO << "Lost the connection from " << conn->remote_addr();
        }
    });
    server.Init();
    server.Start();
    loop.Run();

    evpp::ssl::SSL_CTX_free();

    return 0;
}
Client
/** @file tls_client.h
  * @brief 
  * @author xmcy0011@sina.com
  * @date 5/17/21
  */

#include "evpp/ssl/ssl_client.h"

#ifdef WIN32
struct OnApp {
    OnApp() {
        // Initialize net work.
        WSADATA wsaData;
        // Initialize Winsock 2.2
        int nError = WSAStartup(MAKEWORD(2, 2), &wsaData);

        if (nError) {
            std::cout << "WSAStartup() failed with error: %d" << nError;
        }

    }
    ~OnApp() {
        system("pause");
    }
} __s_onexit_pause;
#endif

int main(int argc, char *argv[]) {
    std::string addr = "127.0.0.1:8433";
    //std::string addr = "1127.0.0.1:8433";

    if (argc == 2) {
        addr = argv[1];
    }

    evpp::EventLoop loop;
    evpp::ssl::SSLClient client(&loop, addr, "TCPPingPongClient");
    client.SetMessageCallback([&loop, &client](const evpp::TCPConnPtr &conn,
                                               evpp::Buffer *msg) {
        LOG_TRACE << "Receive a message [" << msg->ToString() << "]";
        client.Disconnect();
    });

    client.SetConnectionCallback([](const evpp::TCPConnPtr &conn) {
        if (conn->IsConnected()) {
            LOG_INFO << "Connected to " << conn->remote_addr();
            conn->Send("hello");
        } else {
            conn->loop()->Stop();
        }
    });

    client.Connect();
    loop.Run();

    return 0;
}

WebSocket

详细代码参考:/evpp/examples/ws目录。

/** @file websocket_server.h
  * @brief WebSocketServer示例
  * @author teng.qing
  * @date 2021/5/23
  */
#include "evpp/event_loop.h"
#include "evpp/tcp_callbacks.h"
#include "evpp/ws/web_socket_conn.h"
#include "evpp/ws/web_socket_server.h"
#include "evpp/logging.h"

int main() {
    std::string addr = "0.0.0.0:8002";
    int thread_num = 4;
    evpp::EventLoop loop;

    evpp::ws::WebSocketServer server(&loop, addr, "TlsServer", thread_num);
    server.SetMessageCallback([](const evpp::TCPConnPtr &conn,
                                 evpp::Buffer *msg) {
        LOG_INFO << "recv client msg:len=" << msg->length();
		conn->Send(msg); // At here, we just send the received message back.       
        }
    });
    server.SetConnectionCallback([](const evpp::TCPConnPtr &conn) {
        if (conn->IsConnected()) {
            LOG_INFO << "A new connection from " << conn->remote_addr();
        } else {
            LOG_INFO << "Lost the connection from " << conn->remote_addr();
        }
    });
    server.Init();
    server.Start();
    loop.Run();

    return 0;
}

OpenSSL入门

可以参考我写的:OpenSSL API入门和踩坑大全

WebSocket入门

请移步:WebSocket入门和帧协议详解

参考

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值