使用c++制作微服务计算服务

其他链接

上次使用了go来制作微服务计算服务
go制作微服务计算服务

c++制作标准差服务计算

使用c++的计算服务速度是更快的,一下只是一个计算标准差的函数样例,和go服务之间进行交换可以使用更简单的c,如果使用c++,则可以简化计算过程

#pragma once
#include <vector>
//标准差
//数据是五分钟的,就是sdann
//数据是24小时的,就是sdnn
double get_stddev(std::vector<double> &data);



double get_average(std::vector <double> &data);

cpp如下



double get_stddev(std::vector<double> &data)
{
	double ret = 0.0;
	size_t size = data.size();
	if (size  == 0)
		return -1;
	double sum = std::accumulate(std::begin(data), std::end(data), 0.0);
	double mean = sum / (double)size; //均值
	std::cout << "the mean is " << mean << std::endl;
	double sdnn_2 = 0.0;
	std::for_each(std::begin(data), std::end(data), [&](const double d) {
		sdnn_2 += (d - mean)*(d - mean);
	});

	double sdnn = sqrt(sdnn_2 / (size)); //方
	return sdnn;
}
//求取均值
double get_average(std::vector <double> &data)
{
	size_t size = data.size();
	if (size == 0)
		return -1;
	double sum = std::accumulate(std::begin(data), std::end(data), 0.0);
	double mean = sum / (double)size; //均值
	return mean;
}

c++ http服务 ws服务

使用c++ boost库制作携程服务器,具体我的其他文章里面有
一下是http和ws 服务的c++携程代码,包含了http协议的基本和websocket 协议的基本

#include <boost/asio.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/ip/tcp.hpp>
#include <boost/asio/spawn.hpp>
#include <boost/asio/steady_timer.hpp>
#include <boost/asio/write.hpp>
#include <boost/uuid/detail/sha1.hpp>
#include <iostream>
#include <memory>
#include "util.h"
#include "util_flv_pack.h"
#include "util_hash.h"
#include "c_hub.h"



#define DEFINE_EC \
boost::system::error_code ec;

#define ERROR_RETURN_FALSE \
if(ec){\
   std::cout << ec.message() << std::endl;\
   return false;\
}
#define ERROR_RETURN \
if(ec){ \
   std::cout << ec.message() << std::endl;\
   return ;\
}
#define ERROR_BREAK(ec) \
if (ec){ \
	close();\
	std::cout << ec.message() << std::endl;\
	break;\
}
using namespace boost;
using boost::asio::ip::tcp;

typedef enum en_data_type
{
	en_text = 1,
	en_binary,
	en_ping = 0x09,
	en_pong = 0x0A
}en_data_type;

//the mem has reserved some room for set something,
//1  is  must reserved something for ws head
//2  is  must reserved something for user protocol head
typedef void (*cb_wsdata)(en_data_type type,uint8_t *mem, uint8_t* data, size_t len);
class c_session_webs : public std::enable_shared_from_this<c_session_webs>
{
private:
	void SetSendBufferSize(int nSize)
	{
		boost::asio::socket_base::send_buffer_size size_option(nSize);
		v_socket.set_option(size_option);
	}
	void SetRecvBufferSize(int nSize)
	{
		boost::asio::socket_base::receive_buffer_size size_option(nSize);
		v_socket.set_option(size_option);
	}
public:
	//do not need this ,we just need key
	//std::string v_app_stream;
	uint32_t v_key = 0;
	//time stamp record,every one not the same
	uint32_t v_start_ts = 0;
	bool v_iswebsocket = false;
public:
	explicit c_session_webs(boost::asio::io_context& io_context, tcp::socket socket)
		: v_socket(std::move(socket)),
		/*timer_(io_context),*/
		v_strand(io_context.get_executor())
	{
#ifdef _WIN32
		SetSendBufferSize(1 * 1024 * 1024);
		SetRecvBufferSize(64 * 1024);
#endif
	}

	/*
	The handshake from the client looks as follows :

		GET /chat HTTP/1.1
		Host: server.example.com
		Upgrade: websocket
		Connection: Upgrade
		Sec-WebSocket-Key: dGhlIHNhbXBsZSBub25jZQ ==
		Origin: http://example.com
		Sec-WebSocket-Protocol: chat, superchat
		Sec-WebSocket-Version: 13


		GET /chat HTTP/1.1
		Host: 127.0.0.1:9000
		Connection: Upgrade
		Pragma: no-cache
		Cache-Control: no-cache
		Upgrade: websocket
		Origin: file://
		Sec-WebSocket-Version: 13
		User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.104 Safari/537.36
		Accept-Encoding: gzip, deflate, br
		Accept-Language: zh-CN,zh;q=0.8
		Sec-WebSocket-Key: 1M9Y1T8iMgTLepYQGDFoxg==
		Sec-WebSocket-Extensions: permessage-deflate; client_max_window_bits
	*/

	void func_hand_http(c_header_map &m, boost::asio::yield_context &yield);
	bool func_hand_shake(boost::asio::yield_context &yield)
	{
		int fret = -1;
		DEFINE_EC
		asio::streambuf content_;
		size_t length = asio::async_read_until(v_socket, content_, "\r\n\r\n", yield[ec]);
		ERROR_RETURN_FALSE
		asio::streambuf::const_buffers_type bufs = content_.data();
		std::string lines(asio::buffers_begin(bufs), asio::buffers_begin(bufs) + length);
		c_header_map m;
		string query; // GET /live/1001 => the query is live/1001
		
		if (fetch_head_info(lines, m, query) == -1) //NOT GET or http protocol
			return false;
		//v_key is the hash value
		v_key = hash_add(query.c_str(), HASH_PRIME_MIDDLE);
		auto iter = m.find("Upgrade");
		if (iter == m.end()) //ishttp
		{
			//it is the http protocol ,but not websocket
			func_hand_http(m,yield);
			size_t ret = boost::asio::async_write(v_socket, boost::asio::buffer(FLV_HTTP_HEADERS, FLV_HTTP_HEADERS_LEN), yield[ec]);
			ERROR_RETURN_FALSE
			if (c_flvhubs::instance()->push_session(v_key, shared_from_this(), true) == NULL)
			{
				//we can not find the stream 
			   return false;
			}
			return true;
		}
		else
		{
			//is websocket protocol
			v_iswebsocket = true;
			std::string response, key, encrypted_key;
			//find the get
			//std::string request;
			size_t n = lines.find_first_of('\r');
			//find the Sec-WebSocket-Key
			size_t pos = lines.find("Sec-WebSocket-Key");
			if (pos == lines.npos)
				return false;
			size_t end = lines.find("\r\n", pos);
			key = lines.substr(pos + 19, end - pos - 19) + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
			//get the base64 encode string with sha1
#if 1
			boost::uuids::detail::sha1 sha1;
			sha1.process_bytes(key.c_str(), key.size());
#endif
#if 0
			SHA1 sha;
			unsigned int message_digest[5];
			sha.Reset();
			sha << server_key.c_str();
			sha.Result(message_digest);
#endif
			unsigned int digest[5];
			sha1.get_digest(digest);

			for (int i = 0; i < 5; i++) {
				digest[i] = htonl(digest[i]);
			}

			encrypted_key = base64_encode(reinterpret_cast<const uint8_t*>(&digest[0]), 20);

			/*
			The handshake from the server looks as follows :

			HTTP / 1.1 101 Switching Protocols
			Upgrade : websocket
			Connection : Upgrade
			Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK + xOo =
			Sec-WebSocket-Protocol: chat
			 */
			 //set the response text
			response.append("HTTP/1.1 101 WebSocket Protocol Handshake\r\n");
			response.append("Upgrade: websocket\r\n");
			response.append("Connection: Upgrade\r\n");
			response.append("Sec-WebSocket-Accept: " + encrypted_key + "\r\n\r\n");
			//response.append("Sec-WebSocket-Protocol: chat\r\n");
			//response.append("Sec-WebSocket-Version: 13\r\n\r\n");
			size_t ret = boost::asio::async_write(v_socket, boost::asio::buffer(response), yield[ec]);
			ERROR_RETURN_FALSE
			c_flvhubs::instance()->push_session(v_key, shared_from_this());
		}
		//calculate the hash key 
		
		
		
		return true;
	}

	bool func_set_head_send(uint8_t * frame, int len /*payloadlen*/, int framelen, asio::yield_context &yield)
	{
		*frame = 0x81;//0x81; 1000 0001 text code ; // 1000 0010 binary code
		//*frame = 0x82;
		if (len <= 125) {
			//数据长度小于1个字节
			//mask bit is 0
			*(frame + 1) = (uint8_t)len;
		}
		else if (len <= 0xFFFF) { //65535
			//数据长度小于2个字节
			*(frame + 1) = 126;
			*(frame + 2) = len & 0x000000FF;
			*(frame + 3) = (len & 0x0000FF00) >> 8;
		}
		else {
			//数据长度为8个字节
			*(frame + 1) = 127;
			*(frame + 2) = len & 0x000000FF;
			*(frame + 3) = (len & 0x0000FF00) >> 8;
			*(frame + 4) = (len & 0x00FF0000) >> 16;
			*(frame + 5) = (len & 0xFF000000) >> 24;
			*(frame + 6) = 0;
			*(frame + 7) = 0;
			*(frame + 8) = 0;
			*(frame + 9) = 0;
		}

		DEFINE_EC
		//send the data
		asio::async_write(v_socket, asio::buffer(frame, framelen), yield[ec]);
		if (ec)
		{
			return false;
		}
		return true;
	}


	bool func_recv_message(asio::yield_context &yield)
	{
	/* RFC 6455
	  0                   1                   2                   3
	  0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
	 +-+-+-+-+-------+-+-------------+-------------------------------+
	 |F|R|R|R| opcode|M| Payload len |    Extended payload length    |
	 |I|S|S|S|  (4)  |A|     (7)     |             (16/64)           |
	 |N|V|V|V|       |S|             |   (if payload len==126/127)   |
	 | |1|2|3|       |K|             |                               |
	 +-+-+-+-+-------+-+-------------+ - - - - - - - - - - - - - - - +
	 |     Extended payload length continued, if payload len == 127  |
	 + - - - - - - - - - - - - - - - +-------------------------------+
	 |                               |Masking-key, if MASK set to 1  |
	 +-------------------------------+-------------------------------+
	 | Masking-key (continued)       |          Payload Data         |
	 +-------------------------------- - - - - - - - - - - - - - - - +
	 :                     Payload Data continued ...                :
	 + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +
	 |                     Payload Data continued ...                |
	 +---------------------------------------------------------------+
*/
		DEFINE_EC
		unsigned char code[2];
		size_t n = asio::async_read(v_socket, asio::buffer(&code[0], sizeof(code)), yield[ec]);
		ERROR_RETURN_FALSE
		unsigned char fin = code[0] >> 7;
		unsigned char opcode = code[0] & 0x0f; //00001111 //opcode four bit
		if (fin == char(0x00))
		{
			//1 the message's last fragment
			//0 not the last fragment 
			
			return false;
		}
		
		switch (opcode)
		{
		case 0x01:

			//a text frame
		case 0x02:
			//a binary frame
			break;
		case 0x08:
			//%x8 denotes a connection close rfc6455
			std::cout << "connection close" << std::endl;
			return false;
		case 0x09://WebSocket服务端向客户端发送ping,服务与服务之间可以发送保持链接
			//denotes a ping
			std::cout << "a ping come" << std::endl;
			return true;
		case 0x0A:
			//denotes a pong
			std::cout << "a pong come" << std::endl;
			return true;
		default:
			return false;
		}
		en_data_type type = (en_data_type)opcode;

		unsigned char is_mask = code[1] >> 7;
		//x is 0~126:payload len is x bytes //数据的长度为x字节。
		//x is 126:the conitnue 2 bytes is unsigned uint16 number ,this number is payload length //该无符号整数的值为数据的长度。
		//x is 127:the continue 8 bytes is unsigned uint64 number ,this number is payload length //后续8个字节代表一个64位的无符号整数(最高位为0),该无符号整数的值为数据的长度。

		//qianbo : when send data , we must reserve the room for real data
		int reserved_len = 1;
		uint64_t payloadlen = code[1] & 0x7F;
		if (payloadlen == 0x7E) //0111 1110
		{
			uint16_t len;
			asio::async_read(v_socket, asio::buffer(&len, sizeof(len)), yield[ec]);
			ERROR_RETURN_FALSE
			payloadlen = ntohs(len);
			reserved_len += 3;
		}
		else if (payloadlen == 0x7F) //0111 1111
		{
			uint64_t len;
			asio::async_read(v_socket, asio::buffer(&len, sizeof(len)), yield[ec]);
			ERROR_RETURN_FALSE
			payloadlen = ntohll_1(len);
			reserved_len += 9;
		}
		else
		{ //qianbo <126 bytes
			//if(payloadlen  < 126)
			reserved_len += 1;
		}

		//get mask if exists
		char mask[4];
		if (is_mask)
		{
			asio::async_read(v_socket, asio::buffer(mask, 4), yield[ec]);
			ERROR_RETURN_FALSE
		}
		if (payloadlen > 0)
		{
			//the datalen + ws head len + reserved protocol len
			size_t frame_len = (payloadlen + reserved_len/* + v_respro_len*/);
			uint8_t *frame = new uint8_t[frame_len];
			uint8_t *data = frame + reserved_len /*+ v_respro_len*/;
			asio::async_read(v_socket, asio::buffer(data, payloadlen), yield[ec]);
			ERROR_RETURN_FALSE
			if (is_mask)
			{
				//get the real data
				for (uint64_t i = 0; i < payloadlen; i++)
				{
					data[i] = data[i] ^ mask[i % 4];
				}
			}

			//data[payloadlen] = '\0';
			//std::cout << data << std::endl;
			if (v_cb != NULL)
				v_cb(type, frame, data, frame_len);
			//echo ,send back to session
			//func_set_head_send(frame, payloadlen, frame_len, yield);

			delete[] frame;
		}
		return true;
	}
	void go()
	{
		auto self(shared_from_this());
		boost::asio::spawn(v_strand,
			[this, self](boost::asio::yield_context yield)
		{
			//try
			//{
				//timer_.expires_from_now(std::chrono::seconds(10));
				
				if (func_hand_shake(yield) == false)
				{
					std::cout << "not hand shake" << std::endl;
					return;
				}
				for (;;)
				{
					bool ret = func_recv_message(yield);
					if (!ret)
					{
						close();
						break;
					}
				}
			//}
			//catch (std::exception& e)
			//{
			//	std::cout << "some is error:" << e.what() << std::endl;
			//	close();
			//	//timer_.cancel();
			//}
		});
	}
	void func_setcb(cb_wsdata cb, int len)
	{
		v_cb = cb;
	}
protected:

	//asio::steady_timer timer_;
	asio::io_context v_ioctx;
	asio::strand<boost::asio::io_context::executor_type> v_strand;
	cb_wsdata v_cb = NULL;
	std::string v_get;//like /live/1001

public:
	tcp::socket v_socket;
	//has end meta data
	int v_has_send_meta = 0;
	//stream have video ?
	uint8_t v_has_video = 0;
	//stream have audio?
	uint8_t v_has_audio = 0;
	//was send video head meta
	int v_has_send_video_head = 0;
	//was send audio head meta
	int v_has_send_audio_head = 0;
	//was send key frame 
	int v_has_sent_key_frame = 0;

	void close()
	{
		if (v_socket.is_open())
			v_socket.close();
	}
};

util.h

用到的解析http的部分函数

/*
   lines :http protocol content lines   =>GET /live/1001
   buf   :let the url into this buffer  => live/1001
   buflen:the buf's length
*/
static int fetch_head_get(const char * lines, char *buf,int buflen)
{
	size_t l = strlen(lines);
	if (l < 6)
		return 0;
	//it is GET protocol
	if (strncmp(lines, "GET ", 4) != 0)
		return -1;
	char *pos = buf;
	//URL->GET /live/image ==> get the live/image to buf
#if 0
	char *ori = (char*)&lines[5];
	while (*(ori++) != ' ');
	size_t num = --ori - (lines + 5);
#endif
#define START_P 5
	for (size_t i = START_P; i < l,i<buflen+ START_P; i++)
	{
		if (lines[i] == ' ')
			break;
		*pos++ = lines[i];
	}
	*pos = '\0';
	return (int)(pos-buf);
}
//ret is the /chat like this
// we must add the post protocol
static int fetch_head_info(std::string &lines, c_header_map &hmap, std::string &ret)
{
	if (strncmp(lines.c_str(), "GET ", 4) != 0)
		return -1;
	//not support now
	if (strncmp(lines.c_str(), "POST ", 5 == 0))
		return -2;
	std::istringstream s(lines);
	std::string request;
	std::getline(s, request);
	if (request[request.size() - 1] == '\r')
	{
		request.pop_back();
		//request.erase(request.end() - 1);//the same with pop_back
		//GET /chat HTTP/1.1
		size_t i= 5;
		size_t lmax = request.size();
		while (request[++i] != ' ' && i<lmax);
		if (i == lmax - 1)
			return -1;
		ret = request.substr(5, i - 5);
	}
	else
		return -1;

	hmap.clear();
	std::string header;
	std::string::size_type end;

	while (std::getline(s, header) && header != "\r")
	{
		if (header[header.size() - 1] == '\r')
		{
			//header.pop_back(); //or use this function
			header.erase(header.end() - 1); //remove last char
			end = header.find(": ", 0);

			if (end != std::string::npos)
			{
				std::string key = header.substr(0, end);
				std::string value = header.substr(end + 2);
				hmap[key] = value;
			}
		}
	}

	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qianbo_insist

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值