Как подключить клиент websocket к серверу с URI? - PullRequest
0 голосов
/ 06 августа 2020

У меня есть сервер URI, как этот

WS: // хост: порт маркер = eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVmMTA2MWFmNjViYzY5MDQ4ZGJmODc1YSIsImlhdCI6MTU5NjU0NTAxNCwiZXhwIjo0NzUyMzA1MDE0fQ.E-WuI5jSow69WZPZtQbVKkNR8TIO1DmYwYLgaqREkfE

и хотите подключить мой WebSocket cl inet с этим сервером. Я использую библиотеку boost websocket.

Как я могу подключить свой cl inet к серверу с этим URI.

Вот пример кода.

клиент .hpp


#include "json.h"

#include <iostream>
#include <string>

#include <boost/beast/core.hpp>
#include <boost/beast/ssl.hpp>
#include <boost/beast/websocket.hpp>
#include <boost/asio/connect.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/asio/ssl/stream.hpp>
#include <boost/beast/websocket/ssl.hpp>

#include <opencv2/opencv.hpp>

#include <openssl/sha.h>
#include <openssl/evp.h>
#include <openssl/bio.h>
#include <openssl/buffer.h>

namespace beast = boost::beast;
namespace http = beast::http;
namespace websocket = beast::websocket;
namespace net = boost::asio;
using tcp = boost::asio::ip::tcp;

namespace ssl = boost::asio::ssl;


class client {
public:
    client(const std::string &host, const std::string &port, const std::string& token);

public:
    template<typename TValue>
    void append_send_data(const std::string &key, const TValue &value) noexcept;

public:
    void send() noexcept;

    std::string perform_handshake(std::string url, std::string socketIoResource);

private:
    char *base64_encode(const unsigned char *input, int length) noexcept;
    std::string encode_frame(const cv::Mat &frame) noexcept;

private:
    std::string host_;
    std::string port_;
    std::string token_;
    net::io_context ioc_;
    tcp::resolver resolver_;
    websocket::stream<tcp::socket> ws_;
//    ssl::context ctx_;
//    websocket::stream<beast::ssl_stream<tcp::socket>> ws_;

    nlohmann::json send_data_;
};

#include "client_impl.hpp"

client_impl.hpp

#include "client.h"

#include <boost/shared_ptr.hpp>
#include <boost/regex.hpp>
#include <boost/asio.hpp>
#include <boost/bind.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>

client::client(const std::string &host, const std::string &port, const std::string& token)
        : host_(host)
        , port_(port)
        , token_(token)
        , ioc_{}
        , resolver_(ioc_)
        , ws_(ioc_)
{
}

void client::send() noexcept {
    auto const results = resolver_.resolve(host_, port_);

    auto ep = net::connect(ws_.next_layer(), results);
    
    host_ += ':' + std::to_string(ep.port())+"?"+""+token_;

    ws_.handshake(host_, "/");

    ws_.write(net::buffer(std::string(send_data_.dump())));

    // Debug
    beast::flat_buffer buffer;
    ws_.read(buffer);
    std::cout << beast::make_printable(buffer.data()) << std::endl;

    std::cout << "Data sended!\n";
    send_data_.clear();
}

char *client::base64_encode(const unsigned char *input, int length) noexcept {
    BIO *bmem, *b64;
    BUF_MEM *bptr;
    b64 = BIO_new(BIO_f_base64());
    bmem = BIO_new(BIO_s_mem());
    b64 = BIO_push(b64, bmem);
    BIO_write(b64, input, length);
    BIO_flush(b64);
    BIO_get_mem_ptr(b64, &bptr);
    char *buff = (char *) malloc(bptr->length);
    memcpy(buff, bptr->data, bptr->length - 1);
    buff[bptr->length - 1] = 0;
    BIO_free_all(b64);
    return buff;
}

std::string client::encode_frame(const cv::Mat &frame) noexcept {
    std::vector<uchar> buf;
    cv::imencode(".jpg", frame, buf);
    std::string str = base64_encode(buf.data(), buf.size());
    return str;
}

template<typename TValue>
void client::append_send_data(const std::string &key, const TValue &value) noexcept {
    std::string pass_value;
    if constexpr (std::is_same<TValue, std::string>::value) {
        pass_value = value;
    } else {
        pass_value = boost::lexical_cast<std::string>(value);
    }
    send_data_[key] = pass_value;
}

template<>
void client::append_send_data<cv::Rect2f>(const std::string &key, const cv::Rect2f &value) noexcept {
    nlohmann::json rect_json;

    rect_json["x"] = value.x;
    rect_json["y"] = value.y;
    rect_json["width"] = value.width;
    rect_json["height"] = value.height;

    send_data_[key] = rect_json;
}

template<>
void client::append_send_data<cv::Mat>(const std::string &key, const cv::Mat &value) noexcept {
    send_data_[key] = encode_frame(value);

}

main. cpp

#include "client.h"

#include <iostream>

int main() {
    client cl{"192.168.11.21", "5555", "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6IjVmMTA2MWFmNjViYzY5"
                                      "MDQ4ZGJmODc1YSIsImlhdCI6MTU5NjU0NTAxNCwiZXhwIjo0NzUyMzA1MDE0fQ.E-WuI5jSow69WZPZtQ"
                                      "bVKkNR8TIO1DmYwYLgaqREkfE\n\r"};
    
    int a = 2;
    while(a--) {
        cl.append_send_data("class", "person");
        cl.append_send_data("frame", cv::Mat(200,300,CV_8UC1));
        cl.append_send_data("bbox", cv::Rect2f(4.0, 5.0, 4,8));
        cl.send();
    }

    return 0;
}
...