当前位置:网站首页>WEBSOCKETPP使用简介+demo
WEBSOCKETPP使用简介+demo
2022-07-30 18:35:00 【一只公羊】
标题一、C++跨平台集成WEBSOCKETPP
1. WEBSOCKETPP使用
1.1 整体使用流程
从Websocketpp的例子中,拷贝需要用到的头文件包含和一些类型重定义
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
using websocketpp::connection_hdl;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
using websocketpp::lib::bind;
typedef websocketpp::server<websocketpp::config::asio> server;
typedef server::message_ptr message_ptr;
// 生成server对象
server m_server;
// 初始化m_server
m_server.set_access_channels(websocketpp::log::alevel::none); // 设置打印的日志等级
m_server.init_asio(); // 初始化asio
m_server.set_open_handler(bind(&XXXClass::on_open_func_ptr, this, ::_1)); // 绑定websocket连接到来时的回调函数
m_server.set_close_handler(bind(&XXXClass::on_close_func_ptr, this, ::_1)); // 绑定websocket连接断开时的回调函数
m_server.set_message_handler(bind(&XXXClass::on_message_func_ptr, this, ::_1, ::_2)); // 绑定websocket连接有消息到来时的回调函数
上面三个回调函数的原型如下,我是将server对象直接封装到一个类里面使用的,因此这里绑定的回调函数可以直接使用类的方法。Websocketpp也提供了其他很多环节上的回调函数设定,可自行查看其源代码进行了解。
class XXXClass
{
public :
void on_open_func_ptr(connection_hdl hdl);
void on_close_func_ptr(connection_hdl hdl);
void on_message_func_ptr(connection_hdl hdl, message_ptr msg);
}
回调参数中的connection_hdl是一个weak_ptr,如果需要将连接存到容器中以便管理,则不能使用传入的hdl,需要使用
server::connection_ptr con = m_server.get_con_from_hdl(hdl);
获得的con是个shared_ptr,再调用
void *con_ptr = con->get();
可以得到这个连接的实际对象的地址,但websocketpp对我们隐藏了其对象的结构,只给了我们一个void*,不过用于在每次回调时区分不同的客户端足够了。
当websocket有新消息到来时,我们可以通过
std::string msg_str = msg->get_payload();
直接获取到传输的内容。
以上,就是websocketpp集成后的简单使用流程,server对象其实还提供了很多的使用方法以及回调绑定功能,等有时间我再详细研究,现在这几个已经能满足我的需求了。
#include <websocketpp/config/asio_no_tls.hpp>
#include <websocketpp/server.hpp>
#include <iostream>
#include "HG.h"
typedef websocketpp::server<websocketpp::config::asio> server;
using websocketpp::lib::bind;
using websocketpp::lib::placeholders::_1;
using websocketpp::lib::placeholders::_2;
// pull out the type of messages sent by our config
typedef server::message_ptr message_ptr;
// Define a callback to handle incoming messages
void on_message(server* s, websocketpp::connection_hdl hdl, message_ptr msg)
{
HG hg;
std::string res = "指令失效";
std::cout << "on_message called with hdl: " << hdl.lock().get()
<< " and message: " << msg->get_payload()
<< std::endl;
// check for a special command to instruct the server to stop listening so
// it can be cleanly exited.
if (msg->get_payload() == "stop-listening")
{
s->stop_listening();
return;
}
if (msg->get_payload() == "v")
{
try
{
hg.Version();
s->send(hdl, hg.m_strQR, msg->get_opcode());
}
catch (websocketpp::exception const& e)
{
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
return;
}
if (msg->get_payload() == "x")
{
try
{
hg.Scan();
res = hg.m_strQR;
s->send(hdl, res, msg->get_opcode());
}
catch (websocketpp::exception const& e)
{
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
return;
}
try
{
s->send(hdl, res, msg->get_opcode());
}
catch (websocketpp::exception const& e)
{
std::cout << "Echo failed because: "
<< "(" << e.what() << ")" << std::endl;
}
}
void on_open(server* s, websocketpp::connection_hdl hdl)
{
std::cout << "on_open called with hdl: " << hdl.lock().get() << std::endl;
}
void on_close(server* s, websocketpp::connection_hdl hdl)
{
std::cout << "on_close called with hdl: " << hdl.lock().get() << std::endl;
}
void on_fail(server* s, websocketpp::connection_hdl hdl)
{
std::cout << "on_fail called with hdl: " << hdl.lock().get() << std::endl;
}
int main()
{
// Create a server endpoint
server echo_server;
try
{
// Set logging settings
echo_server.set_access_channels(websocketpp::log::alevel::all);
echo_server.clear_access_channels(websocketpp::log::alevel::frame_payload);
// Initialize Asio
echo_server.init_asio();
// Register our message handler
echo_server.set_open_handler(bind(&on_open, &echo_server, ::_1));
echo_server.set_message_handler(bind(&on_message, &echo_server, ::_1, ::_2));
echo_server.set_close_handler(bind(&on_close, &echo_server, ::_1));
// Listen on port 9002
echo_server.listen(9002);
// Start the server accept loop
echo_server.start_accept();
// Start the ASIO io_service run loop
echo_server.run();
}
catch (websocketpp::exception const& e)
{
std::cout << e.what() << std::endl;
}
catch (...)
{
std::cout << "other exception" << std::endl;
}
}
#pragma once
#include <vector>
#include <string>
class HG
{
void SplitScannerName(char* scannerNames, std::vector<std::string>& vecScannerName);
int ConvertScannerNameToID(std::vector<std::string>& vecScannerName);
public:
void Scan();
std::string m_strQR;
void Version();
};
#include "HG.h"
#include "windows.h"
#include "tchar.h"
#include "io.h"
typedef struct {
char szFpImage[258]; // 发票扫描图像文件名
char szFpCode[20]; // 发票代码
char szFpSeriaoNo[20]; // 发票印刷序号
char szFpCode1[20];
char szFpSeriaoNo1[20]; // 发票印刷序号
char szFpEnVersion[10]; // 加密版本号
char szFpDate[20]; // 发票开票日期
char szFpTaxRate[10]; // 税率
char szFpBuyerTaxNo[30]; // 购方纳税号
char szFpSellerTaxNo[30]; // 销方纳税号
char szFpTotal[40]; // 价税合计
char szFpSum[40]; // 金额
char szFpTax[40]; // 税额
char szFpCryptograph[1024]; // 密文数据
char szFpTaxDiskNo[16]; // 总参版发票机器编号
}VATDATA, * PVATDATA;
typedef struct {
wchar_t szGoodsName[128]; //1.物品名称
wchar_t szGoodsUnit[32]; //2.物品单位
char szGoodsNum[24]; //3.物品数量
}GOODSDATA, * PGOODSDATA;
typedef struct {
wchar_t szFpBuyerName[128]; //1.购方企业名称
wchar_t szFpSellerName[128];//2.销方企业名称
char szGoodsRows[4]; //3.物品行数
GOODSDATA szGoodsData[8]; //4.物品信息数组
}VATEXTDATA, * PVATEXTDATA;
//网认识别所需接口
int (WINAPI* lpFpGetVersion)(int nCompany, int nScanner);
int (WINAPI* lpFpScannerInitialize)(void);
int (WINAPI* lpFpScannerTerminate)(int wAction);
int (WINAPI* lpFpScanNewPage)(PVATDATA lpFpBuffer, PVATEXTDATA lpFpExtBuffer, int* isBarCode, int Multistream);
bool (WINAPI* lpFpGetVersionInfo)(char* szVersionInfo, int BufferLen);
int (WINAPI* lpFpEnumScannerName)(char* szScannerNames, int BufferLen);
bool (WINAPI* lpFpGetElementCell)(int id, long& left, long& top, long& right, long& bottom);
bool (WINAPI* lpFpGetPrintNo)(wchar_t* szBuffer, int buffLen);
bool (WINAPI* lpFpGetPrintCode)(wchar_t* szBuffer, int buffLen);
int (WINAPI* lpFpGetInvoiceName)(wchar_t* szBuffer, int buffLen);
int (WINAPI* lpFpGetVatType)(void);
bool (WINAPI* lpFpGetVerifyNo)(char* szBuffer, int buffLen);
bool (WINAPI* lpFpGetQRString)(char* szBuffer, int buffLen);
typedef struct
{
char scannerName[MAX_PATH];
int scannerID;
}SCANNER_INFO;
static SCANNER_INFO arraryScannerInfo[] =
{
{
"S525II", 76},
{
"L7280+", 139},
{
"U610", 124},
{
"M2200", 125},
{
"U3200+", 114},
{
"U370II", 64},
{
"M1200II", 118},
{
"GW3025", 136},
{
"M1230", 152},
{
"S825+", 107},
{
"DL2020", 148},
{
"WI2025", 161},
{
"S680", 162},
{
"U5090", 163},
{
"S610+", 164},
{
"M1280+", 131}
};
std::string generate_image()
{
char ansi[256] = {
0 };
DWORD cur_time = GetTickCount();
_itoa_s(cur_time, ansi, 10);
return ansi;
}
void HG::SplitScannerName(char* scannerNames, std::vector<std::string>& vecScannerName)
{
std::string strTemp = scannerNames;
int startPos = strTemp.find("$");
if (startPos == -1)
return;
strTemp = strTemp.substr(startPos + 1);
while (strTemp.find("$") != -1)
{
int nextPos = strTemp.find("$");
std::string strName = strTemp.substr(0, nextPos);
vecScannerName.push_back(strName);
strTemp = strTemp.substr(nextPos + 1);
}
}
int HG::ConvertScannerNameToID(std::vector<std::string>& vecScannerName)
{
int supportScannerNum = sizeof(arraryScannerInfo) / sizeof(arraryScannerInfo[0]);;
for (int i = 0; i < vecScannerName.size(); i++)
for (int j = 0; j < supportScannerNum; j++)
if (vecScannerName[i].compare(arraryScannerInfo[j].scannerName) == 0)
return arraryScannerInfo[j].scannerID;
return 0;
}
void HG::Version()
{
HINSTANCE hInst = ::LoadLibrary(_T("scanreco.dll"));
if (hInst == NULL)
{
m_strQR = "LoadLibrary scanreco.dll失败!";
return;
}
(FARPROC&)lpFpGetVersionInfo = ::GetProcAddress(hInst, "FpGetVersionInfo");
if (lpFpGetVersionInfo == NULL)
{
m_strQR = "FpGetVersionInfo()获取接口失败!";
return;
}
char szBuffer[16] = {
0 };
lpFpGetVersionInfo(szBuffer, 16);
std::string szBuffer_string(szBuffer);
m_strQR = szBuffer_string;
::FreeLibrary(hInst);
}
void HG::Scan()
{
VATDATA FpBuffer;
VATEXTDATA FpExtBuffer;
int isBarCode = 0;
int MultiStream = 20;
HINSTANCE hInst = ::LoadLibrary(_T("scanreco.dll"));
if (hInst == NULL)
{
m_strQR = "LoadLibrary()失败!";
return;
}
(FARPROC&)lpFpGetVersion = ::GetProcAddress(hInst, "FpGetVersion");
(FARPROC&)lpFpScannerInitialize = ::GetProcAddress(hInst, "FpScannerInitialize");
(FARPROC&)lpFpScannerTerminate = ::GetProcAddress(hInst, "FpScannerTerminate");
(FARPROC&)lpFpScanNewPage = ::GetProcAddress(hInst, "FpScanNewPage");
(FARPROC&)lpFpEnumScannerName = ::GetProcAddress(hInst, "FpEnumScannerName");
(FARPROC&)lpFpGetElementCell = ::GetProcAddress(hInst, "FpGetElementCell");
//
(FARPROC&)lpFpGetPrintNo = ::GetProcAddress(hInst, "FpGetPrintNo");
(FARPROC&)lpFpGetPrintCode = ::GetProcAddress(hInst, "FpGetPrintCode");
(FARPROC&)lpFpGetInvoiceName = ::GetProcAddress(hInst, "FpGetInvoiceName");
//
(FARPROC&)lpFpGetVatType = ::GetProcAddress(hInst, "FpGetVatType");
(FARPROC&)lpFpGetVerifyNo = ::GetProcAddress(hInst, "FpGetVerifyNo");
(FARPROC&)lpFpGetQRString = ::GetProcAddress(hInst, "FpGetQRString");
//
if (lpFpGetVersion == NULL || lpFpScannerInitialize == NULL || lpFpScannerTerminate == NULL ||
lpFpScanNewPage == NULL || lpFpEnumScannerName == NULL || lpFpGetElementCell == NULL || lpFpGetPrintNo == NULL || lpFpGetPrintCode == NULL || lpFpGetInvoiceName == NULL ||
lpFpGetVatType == NULL || lpFpGetVerifyNo == NULL || lpFpGetQRString == NULL)
{
m_strQR = "获取函数指针失败!";
::FreeLibrary(hInst);
return;
}
//获得USB连接的影源扫描仪列表
char szScannerName[MAX_PATH] = {
0 };
int scannerNum = lpFpEnumScannerName(szScannerName, MAX_PATH);
if (szScannerName == 0 || scannerNum == 0)
{
m_strQR = "USB口没有连接影源扫描仪!";
::FreeLibrary(hInst);
return;
}
//分解列表并转换成扫描仪ID
std::vector<std::string> vecScannerNames;
SplitScannerName(szScannerName, vecScannerNames);
int scannerID = ConvertScannerNameToID(vecScannerNames);
if (scannerID == 0)
{
m_strQR = "没有连接影源扫描仪!";
::FreeLibrary(hInst);
return;
}
//Step 1 判断识别库版本号,目前为710
if (lpFpGetVersion(79318044, scannerID) != 710)
{
m_strQR = "FpGetVersion失败!";
::FreeLibrary(hInst);
return;
}
//Step 2 初始化扫描仪和识别核心
if (lpFpScannerInitialize() != 0)
{
m_strQR = "FpScannerInitialize()失败!";
::FreeLibrary(hInst);
return;
}
//Step 3 扫描并识别,缺纸则结束识别
int RetCode = 0;
while (RetCode == 0)
{
memset(&FpBuffer, 0, sizeof(FpBuffer));
memset(&FpExtBuffer, 0, sizeof(FpExtBuffer));
RetCode = lpFpScanNewPage(&FpBuffer, &FpExtBuffer, &isBarCode, MultiStream);
if (RetCode == 0)
{
//
if (_access("c:/fpimage/ScanTempCF.jpg", 00) != -1)
{
std::string file_name = generate_image();
file_name += ".jpg";
std::string dst_file_name = "c:/fpimage/";
dst_file_name += file_name;
::CopyFileA("c:/fpimage/ScanTempCF.jpg", dst_file_name.c_str(), true);
}
//
std::string temp;// = FpBuffer.szFpSeriaoNo;
temp.empty();
int fptype = lpFpGetVatType();
if (fptype == 0)
temp = "发票类型:专用发票";
if (fptype == 1)
temp = "发票类型:普通发票";
if (fptype == 2)
temp = "发票类型:未知发票";
m_strQR += temp;
//
temp.empty();
std::string szFpCode_string(FpBuffer.szFpCode);
temp = "发票代码:" + szFpCode_string;
m_strQR += temp;
//
//temp.empty();
//temp.Format("发票号码:%s\r\n", FpBuffer.szFpSeriaoNo);
//m_strQR += temp;
//temp.empty();
//temp.Format("开票日期:%s\r\n", FpBuffer.szFpDate);
//m_strQR += temp;
//temp.empty();
//temp.Format("购方税号:%s\r\n", FpBuffer.szFpBuyerTaxNo);
//m_strQR += temp;
//temp.empty();
//temp.Format("销方税号:%s\r\n", FpBuffer.szFpSellerTaxNo);
//m_strQR += temp;
//temp.empty();
//temp.Format("金额:%s\r\n", FpBuffer.szFpSum);
//m_strQR += temp;
//temp.empty();
//temp.Format("税额:%s\r\n", FpBuffer.szFpTax);
//m_strQR += temp;
//temp.empty();
//temp.Format("合计金额:%s\r\n", FpBuffer.szFpTotal);
//m_strQR += temp;
//temp.empty();
//temp.Format("机器编号:%s\r\n", FpBuffer.szFpTaxDiskNo);
//m_strQR += temp;
//
char ansi_verify_no[256] = {
0 };
lpFpGetVerifyNo(ansi_verify_no, 255);
std::string ansi_verify_no_string(ansi_verify_no);
char ansi_qr[4096] = {
0 };
lpFpGetQRString(ansi_qr, 4095);
std::string ansi_qr_string(ansi_qr);
temp.empty();
temp = "校验码: " + ansi_verify_no_string + "QR: " + ansi_qr_string;
m_strQR += temp;
}
}
#if 0
if (RetCode == 0)
{
wchar_t printNo[256] = {
0 };
wchar_t printCode[256] = {
0 };
wchar_t invoiceName[256] = {
0 };
lpFpGetPrintNo(printNo, 255);
lpFpGetPrintCode(printCode, 255);
lpFpGetInvoiceName(invoiceName, 255);
char ansiNo[256] = {
0 };
::WideCharToMultiByte(CP_ACP, 0, printNo, wcslen(printNo), ansiNo, 255, 0, 0);
char ansiCode[256] = {
0 };
::WideCharToMultiByte(CP_ACP, 0, printCode, wcslen(printCode), ansiCode, 255, 0, 0);
char ansiName[256] = {
0 };
::WideCharToMultiByte(CP_ACP, 0, invoiceName, wcslen(invoiceName), ansiName, 255, 0, 0);
CString temp1;
temp1.Format("打印代码: %s\r\n打印号码: %s\r\n发票名称: %s\r\n购方税号: %s\r\n销方税号: %s\r\n密文:%s\r\n", ansiNo, ansiCode, ansiName, FpBuffer.szFpBuyerTaxNo, FpBuffer.szFpSellerTaxNo, FpBuffer.szFpCryptograph);
RECT rcCode, rcNo;
lpFpGetElementCell(0, rcCode.left, rcCode.top, rcCode.right, rcCode.bottom);
lpFpGetElementCell(1, rcNo.left, rcNo.top, rcNo.right, rcNo.bottom);
m_strQR.Format("发票代码: %s: 坐标: left=%d, top = %d, right = %d, bottom = %d\r\n发票号码: %s: 坐标: left=%d, top = %d, right = %d, bottom = %d\r\n", FpBuffer.szFpCode, rcCode.left, rcCode.top, rcCode.right, rcCode.bottom,
FpBuffer.szFpSeriaoNo, rcNo.left, rcNo.top, rcNo.right, rcNo.bottom);
m_strQR += "-------------------------------------------------\r\n";
m_strQR += temp1;
}
}
#endif
//Step 4 终止扫描和识别
lpFpScannerTerminate(0);
//释放网认增值税发票识别库
::FreeLibrary(hInst);
}
边栏推荐
猜你喜欢

生物医学论文有何价值 论文中译英怎样翻译效果好

博纳影通过IPO注册:阿里腾讯是股东 受疫情冲击明显

CCNA-NAT协议(理论与实验练习)

ESP8266-Arduino编程实例-DS18B20温度传感器驱动

Scrapy框架介绍

Graphic LeetCode -- 11. Containers of most water (difficulty: medium)

【Swords Offer】Swords Offer 17. Print n digits from 1 to the largest

经济新闻:错误# 15:初始化libiomp5md。dll,但发现libiomp5md。已经初始化dll。解决方法

基础架构之Mongo

Swiper轮播图片并播放背景音乐
随机推荐
【Pointing to Offer】Pointing to Offer 22. The kth node from the bottom in the linked list
Redis for infrastructure
ESP8266-Arduino programming example-BMP180 air pressure temperature sensor driver
自己需要努力
微博广告分布式配置中心的构建与实践(有彩蛋)
MYSQL (Basic) - An article takes you into the wonderful world of MYSQL
【HMS core】【FAQ】HMS Toolkit典型问题合集1
ByteArrayInputStream 类源码分析
【HMS core】【FAQ】Account Kit、MDM能力、push Kit典型问题合集6
cocos creater 热更重启导致崩溃
EMC VPLEX VS2 SPS电池更换详细探讨
Network Basics (3) 01-Basic Concepts of Networks - Protocols, Host Addresses, Paths and Parameters of URL Addresses & 127.0.0.1 Local Loopback Address & View URL IP Address and Access Ping Space + URL
CMake库搜索函数居然不搜索LD_LIBRARY_PATH
《痞子衡嵌入式半月刊》 第 59 期
3D机器视觉厂商的场景争夺战役
NC | Tao Liang Group of West Lake University - TMPRSS2 "assists" virus infection and mediates the host invasion of Clostridium sothrix hemorrhagic toxin...
基础架构之Mongo
【HMS core】【Analytics Kit】【FAQ】如何解决华为分析付费分析中付款金额显示为0的问题?
SwiftUI iOS Boutique Open Source Project Complete Baked Food Recipe App based on SQLite (tutorial including source code)
【剑指 Offer】剑指 Offer 22. 链表中倒数第k个节点