C++调用java
2015-09-15 09:22
507 查看
#include "IniConfigure.h"
#include "FXProtocol.pb.h"
#include "BPEX_MsgHeader.h"
#include "DataSourcePostControl.h"
#include "BPEX_SourceProvider.h"
#include <cryptopp/hex.h>
#include <cryptopp/default.h>
#include <cryptopp/filters.h>
#include <iomanip>
#include <sstream>
#include "tinyxml/tinyxml.h"
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/date_time/posix_time/time_period.hpp>
#include <boost/date_time/posix_time/time_period.hpp>
#include <boost/date_time/posix_time/time_formatters.hpp>
#include <boost/date_time/posix_time/time_formatters.hpp>
std::string StringEncoderHex(const std::string& decoded, std::string& encoded)
{
CryptoPP::StringSource ss((byte*)decoded.data(), decoded.size(), true,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(encoded)
) // HexEncoder
); // StringSource
return encoded;
}
std::string HexDecodedString(const std::string& encoded, std::string& decoded)
{
CryptoPP::StringSource ss((byte*)encoded.data(), encoded.size(), true /*pumpAll*/,
new CryptoPP::HexDecoder(
new CryptoPP::StringSink(decoded)
) // HexDecoder
); // StringSource
return decoded;
}
//java与C++间的字符转换
jstring CharToJString(JNIEnv* env, const char* pch);
std::string JStringToCString(JNIEnv* env, jstring jstr);
//去空白
std::string& trim(std::string& strtxt);
//指定time_t类型的时间,格式化为YYYYMMDDHH24MISS型的字符串
void FormatTime(time_t time1, char* szTime)
{
struct tm tm1;
#ifdef WIN32
tm1 = *localtime(&time1);
#else
localtime_r(&time1, &tm1);
#endif
sprintf(szTime, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday,
tm1.tm_hour, tm1.tm_min, tm1.tm_sec);
}
//void WriteLog(std::string strLog)
void WriteLog(const char* strLog)
{
FILE* fp = NULL;
static int ICOUNT = 1;
std::string strFile;
strFile = "./log/ReceiveDetail.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
std::string strLogContent;
strLogContent = strLog;
fwrite(strLogContent.data(), 1, strLogContent.size(), fp);
if (0 == (ICOUNT++ % 4096))
{
fwrite("\n", 1, 1, fp);
ICOUNT = 1;
}
fclose(fp);
}
void WriteLogReadHex(const string& strLog)
{
FILE* fp = NULL;
static int ICOUNT = 0;
std::string strFile;
strFile = "./log/ReceiveDetail_Read_Hex.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
std::string strLogContent;
strLogContent = strLog;
fwrite(strLogContent.data(), 1, strLogContent.size(), fp);
ICOUNT += strLogContent.size();
if (0 == (ICOUNT % 4096))
{
fwrite("\n", 1, 1, fp);
ICOUNT = 0;
}
fclose(fp);
}
void WriteLogParseHex(const string& strLog)
{
FILE* fp = NULL;
std::string strFile;
strFile = "./log/ReceiveDetail_Parse_Hex.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
std::string strLogContent;
strLogContent = strLog;
fwrite(strLogContent.data(), 1, strLogContent.size(), fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
void WriteLogB(std::string& strLog)
{
FILE* fp = NULL;
static int ICOUNT = 1;
std::string strFile;
strFile = "./log/ReceiveDetailB.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
//std::string strLogContent;
//strLogContent = strLog;
fwrite(strLog.data(), 1, strLog.size(), fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
void WriteLogD(const std::string& strLog)
{
FILE* fp = NULL;
static int ICOUNT = 1;
std::string strFile;
strFile = "./log/ReceiveDetailB.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
fwrite(strLog.data(), 1, strLog.size(), fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
JavaVM* CBPEXSourceProvider::m_jvm = NULL;
JNIEnv* CBPEXSourceProvider::m_env = NULL;
HINSTANCE CBPEXSourceProvider::m_hInstance = NULL;
jclass CBPEXSourceProvider::m_cls = NULL;
std::string CBPEXSourceProvider::m_JVM_PATH("");
std::string CBPEXSourceProvider::m_JAR_PATH("");
CBPEXSourceProvider::CBPEXSourceProvider()
: m_mul(1000)
, m_strIpAddress("")
, m_strIpPort("")
, m_strHead("")
, m_strUserName("")
, m_strPassWord("")
, m_strRsaPublicKey("")
, m_bStop(false)
, m_changekey(true)
{
}
CBPEXSourceProvider::~CBPEXSourceProvider()
{
if (NULL != m_jvm)
{
//销毁虚拟机并释放动态库
m_jvm->DestroyJavaVM();
::FreeLibrary(m_hInstance);
}
}
bool CBPEXSourceProvider::InitConfig()
{
CIniConfigure iniconfig("DataSourcePort_BPEX.ini", "MAIN");
std::string strMul;
strMul = iniconfig.GetConfigString("MUL", "10000");
m_mul = std::stoi(strMul);
m_strIpAddress = iniconfig.GetConfigString("IP", "");
m_strIpPort = iniconfig.GetConfigString("PORT", "");
m_strHead = iniconfig.GetConfigString("HEAD", "");
m_strUserName = iniconfig.GetConfigString("USERNAME", "");
m_strPassWord = iniconfig.GetConfigString("PASSWORD", "");
m_strRsaPublicKey = iniconfig.GetConfigString("RSAPUBLICKEY", "");
if (m_strIpAddress == "" || m_strIpPort == "" || m_strHead == "" ||
m_strUserName == "" || m_strPassWord == "" || m_strRsaPublicKey == "")
{
return false;
}
m_JVM_PATH = iniconfig.GetConfigString("JVM_PATH", "");
m_JAR_PATH = iniconfig.GetConfigString("JAR_PATH", "");
//初始化JAVA虚拟机
if (true != InitJavaVM())
{
return false;
}
return true;
}
bool CBPEXSourceProvider::InitJavaVM()
{
//定义一个函数指针,下面用来指向JVM中的JNI_CreateJavaVM函数
typedef jint(WINAPI * PFunCreateJavaVM)(JavaVM**, void**, void*);
int res = -1;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
JavaVM* jvm = NULL;
JNIEnv* env = NULL;
/*设置初始化参数*/
//disable JIT,这是JNI文档中的解释,具体意义不是很清楚 ,能取哪些值也不清楚。
//从JNI文档里给的示例代码中搬过来的
options[0].optionString = "-Djava.compiler=NONE";
//设置classpath,如果程序用到了第三方的JAR包,也可以在这里面包含进来
//options[1].optionString = "-Djava.class.path=./BpexQuote.jar";
char strJarPath[256] = {0};
sprintf(strJarPath, "-Djava.class.path=%s", m_JAR_PATH.c_str());
options[1].optionString = strJarPath;
//设置显示消息的类型,取值有gc、class和jni,如果一次取多个的话值之间用逗号格开,如-verbose:gc,class
//该参数可以用来观察C++调用JAVA的过程,设置该参数后,程序会在标准输出设备上打印调用的相关信息
options[2].optionString = "-verbose:NONE";
//设置版本号,版本号有JNI_VERSION_1_1,JNI_VERSION_1_2和JNI_VERSION_1_4
//选择一个根你安装的JRE版本最近的版本号即可,不过你的JRE版本一定要等于或者高于指定的版本号
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 3;
vm_args.options = options;
//该参数指定是否忽略非标准的参数,如果填JNI_FLASE,当遇到非标准参数时,JNI_CreateJavaVM会返回JNI_ERR
vm_args.ignoreUnrecognized = JNI_TRUE;
//加载JVM.DLL动态库
//std::string strJvmLib = "D:\\Program Files (x86)\\Java\\jdk1.8.0_51\\jre\\bin\\client\\jvm.dll";
std::string strJvmLib = m_JVM_PATH;
#ifdef _UNICODE
//格式转换问题
WCHAR wstrJvmLib[MAX_PATH] = {0};
//返回所需的短字符数组空间的个数
DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, strJvmLib.data(), -1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, strJvmLib.data(), -1, wstrJvmLib, dwNum); // 开始转换
HINSTANCE hInstance = ::LoadLibrary(wstrJvmLib);
#else
HINSTANCE hInstance = ::LoadLibrary(strJvmLib.c_str());
#endif
if (hInstance == NULL)
{
return false;
}
//取得里面的JNI_CreateJavaVM函数指针
PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");
//调用JNI_CreateJavaVM创建虚拟机
res = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
if (res < 0)
{
return false;
}
//查找类,返回JAVA类的CLASS对象
jclass cls = env->FindClass("com/ylink/outqut/QuoteLib");
if (NULL == cls)
{
return false;
}
m_hInstance = hInstance;
m_jvm = jvm;
m_env = env;
m_cls = cls ;
return true;
}
void CBPEXSourceProvider::Run()
{
if (InitConfig())
{
boost::thread thrst(boost::bind(&CBPEXSourceProvider::Start, this));
BoostSleep(5);
boost::thread thrde(boost::bind(&CBPEXSourceProvider::ProDeCryptData, this));
}
else
{
std::cout << "读取IP IP端口号 用户密码出错。" << std::endl;
}
return;
}
void CBPEXSourceProvider::Start()
{
if (false == Login())
{
lock_type lock(m_mutex);
m_bStop = true;
m_client.StopConnect();
return;
}
while (!m_bStop)
{
// 接受数据
if (!ReciveData())
{
std::cout << __LINE__ << "ReciveData false!" << std::endl;
break;
}
}
lock_type lock(m_mutex);
m_bStop = true;
return;
}
bool CBPEXSourceProvider::Login()
{
std::string strIpAddress;
std::string strIpPort;
strIpAddress = m_strIpAddress;
strIpPort = m_strIpPort;
m_client.StopConnect();
if (false == Connect(strIpAddress, strIpPort))
{
return false;
}
std::string strUserName = m_strUserName;
std::string strPassWord = m_strPassWord;
std::string strRsaPulicKey = m_strRsaPublicKey;
if (false == GetLoginCredentials(strUserName, strPassWord, strRsaPulicKey))
{
return false;
}
int nDataLen = 0;
int nWriteLen = 0;
nDataLen = m_strLoginCredentials.size();
// 发送登录信息
m_client.SetTimeout(60 * 1000);
nWriteLen = m_client.WriteData(m_strLoginCredentials.data(), nDataLen);
if (nWriteLen == -1)
{
return false;
}
lock_type lock(m_mutex);
m_changekey = true;
return true;
}
bool CBPEXSourceProvider::Connect(std::string strIpAddress, std::string strIpPort)
{
if (true == m_client.IsOpen())
{
return true;
}
m_client.StopConnect();
if (false == m_client.StartConnect(strIpAddress, strIpPort))
{
return false;
}
return true;
}
bool CBPEXSourceProvider::GetLoginCredentials(const std::string& username, const std::string& password, const std::string& rsapulickey)
{
JNIEnv* env = NULL;
jclass cls = NULL;
jobject obj = NULL;
if (NULL != m_env && NULL != m_cls)
{
cls = m_cls;
//JNIEnv和jobject对象都不能跨线程使用
m_jvm->AttachCurrentThread((void**)&env, NULL);
//obj = env->NewGlobalRef(m_obj); //创建一个全局变量
//m_obj = obj;
}
else
{
return false;
}
//根据类的CLASS对象获取该类的实例
obj = env->AllocObject(cls);
if (NULL == obj)
{
return false;
}
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
jmethodID mid = env->GetMethodID(cls, "GetLoginCredentials", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
jstring strjUserName;
jstring strjPassWord;
jstring strjRsaPulicKey;
strjUserName = CharToJString(env, username.c_str());
strjPassWord = CharToJString(env, password.c_str());
strjRsaPulicKey = CharToJString(env, rsapulickey.c_str());
jstring strjLoginCredential;
strjLoginCredential = (jstring)env->CallObjectMethod(obj, mid, strjUserName, strjPassWord, strjRsaPulicKey);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = env->ExceptionOccurred();
if (excp)
{
jclass cls = env->GetObjectClass(excp);
env->ExceptionClear();
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring msg = (jstring) env->CallObjectMethod(excp, mid);
std::cout << JStringToCString(env, msg) << std::endl;
env->ExceptionClear();
}
std::string strLoginCredential;
strLoginCredential = JStringToCString(env, strjLoginCredential);
//std::cout << __LINE__ << ": " << strLoginCredential << std::endl;
m_strLoginCredentials.clear();
std::stringstream sstr;
int a = 5;
sstr << setw(8) << setfill('0') << strLoginCredential.size() ;
m_strLoginCredentials = sstr.str();
m_strLoginCredentials += strLoginCredential;
//获取KEY
jstring strjKey;
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
mid = env->GetMethodID(cls, "GetDEesKey", "()Ljava/lang/String;");
strjKey = (jstring)env->CallObjectMethod(obj, mid);
m_strjKey = strjKey;
std::string strKey;
strKey = JStringToCString(env, strjKey);
//std::cout << __LINE__ << ": " << strKey << std::endl;
m_jvm->DetachCurrentThread();
//WriteLog(strKey.c_str());
//WriteLog(strLoginCredential.c_str());
return true;
}
bool CBPEXSourceProvider::ReciveData()
{
// 读取报文体
size_t nDataLen = 2;
int nRedDataLen = 0;
char szDataStream[1024] = {0};
int count = 1;
while (!m_bStop)
{
memset(szDataStream, 0x00, sizeof(szDataStream));
m_client.SetTimeout(300 * 1000);
nRedDataLen = m_client.ReadData(szDataStream, nDataLen);
//WriteLog(szDataStream);
std::string strHex;
StringEncoderHex(szDataStream, strHex);
WriteLogReadHex(strHex);
if (-1 == nRedDataLen)
{
if (false == Login())
{
break;
}
continue;
}
m_mutex.lock();
m_strQuoteDataStream.append(szDataStream, nRedDataLen);
if (m_strQuoteDataStream.size() > 26)
{
m_cond_proc.notify_one();
}
m_mutex.unlock();
}
m_cond_proc.notify_one();
return false;
}
bool CBPEXSourceProvider::ProDeCryptData()
{
std::string strQuoteDataStream;
JNIEnv* env = NULL;
jclass cls;
jobject obj;
jmethodID des_mid;
jmethodID changekey_mid;
if (NULL != m_env && NULL != m_cls)
{
//JNIEnv和jobject对象都不能跨线程使用
m_jvm->AttachCurrentThread((void**)&env, NULL);
cls = m_cls;
}
else
{
return false;
}
//根据类的CLASS对象获取该类的实例
obj = env->AllocObject(cls);
if (NULL == obj)
{
return false;
}
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
changekey_mid = env->GetMethodID(cls, "SetDesKey", "(Ljava/lang/String;)V");
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
des_mid = env->GetMethodID(cls, "DecryptPackets", "(Ljava/lang/String;)Ljava/lang/String;");
while (!m_bStop)
{
std::string strCiphertext;
if (m_changekey == true)
{
jstring strjKey;
strjKey = m_strjKey;
env->CallObjectMethod(obj, changekey_mid, strjKey);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = env->ExceptionOccurred();
if (excp)
{
jclass cls = env->GetObjectClass(excp);
env->ExceptionClear();
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring msg = (jstring) env->CallObjectMethod(excp, mid);
std::cout << JStringToCString(env, msg) << std::endl;
env->ExceptionClear();
return false;
}
lock_type lock(m_mutex);
m_changekey = false;
}
m_mutex.lock();
if (strQuoteDataStream.size() < 26)
{
m_cond_proc.wait(m_mutex);
}
if (m_strQuoteDataStream.size() >= 2)
{
strQuoteDataStream.append(m_strQuoteDataStream);
m_strQuoteDataStream.clear();
}
m_mutex.unlock();
//获取报文头
std::string strHead = FindPacketHead(strQuoteDataStream);
//对获取到包进行分析处理
if (strQuoteDataStream.size() < 26 || "" == strHead)
{
continue;
}
int iStartPos = 0;
int iEndPos = 0;
//获取第一个报文头的起始位置
if (std::string::npos != strQuoteDataStream.find(strHead, iStartPos))
{
iStartPos = strQuoteDataStream.find(strHead, iStartPos);
}
//对一个报文的长度
unsigned int iPacketLen = stoi(strHead);
if ((iStartPos + (8 + 2) + iPacketLen) > strQuoteDataStream.size())
{
continue;
}
//获取第二个报文头的位置
std::string strValue;
strValue = strQuoteDataStream.substr(iStartPos + 8 + iPacketLen);
strHead = FindPacketHead(strValue);
if ("" == strHead)
{
continue;
}
//获取第一个报文的结束位置
if (std::string::npos != strQuoteDataStream.find(strHead, iStartPos + 8 + iPacketLen))
{
iEndPos = strQuoteDataStream.find(strHead, iStartPos + 8 + iPacketLen);
}
strValue.clear();
strValue = strQuoteDataStream.substr(iStartPos, iEndPos - iStartPos);
std::string strTempValue;
strTempValue = strQuoteDataStream.substr(iEndPos);
strQuoteDataStream.clear();
strQuoteDataStream = strTempValue;
//std::cout << strValue << std::endl;
//WriteLogB(strValue);
std::string strHex;
StringEncoderHex(strValue, strHex);
WriteLogParseHex(strHex);
//心跳报文: 00000018ConnectTestSucceed
if (std::string::npos != strValue.find("ConnectTestSucceed"))
{
continue;
}
jstring strjValue;
strjValue = CharToJString(env, strValue.c_str());
jstring strjPlainText;
strjPlainText = (jstring)env->CallObjectMethod(obj, des_mid, strjValue);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = env->ExceptionOccurred();
if (excp)
{
jclass cls = env->GetObjectClass(excp);
env->ExceptionClear();
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring msg = (jstring) env->CallObjectMethod(excp, mid);
std::cout << JStringToCString(env, msg) << std::endl;
env->ExceptionClear();
WriteLogB(JStringToCString(env, msg));
continue;
}
std::string strPlainText;
strPlainText = JStringToCString(env, strjPlainText);
ParseXMLData(strPlainText);
}
lock_type lock(m_mutex);
m_bStop = true;
m_jvm->DetachCurrentThread();
return true;
}
void CBPEXSourceProvider::BoostSleep(unsigned int nSeconds)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
xt.sec += nSeconds;
boost::thread::sleep(xt);
}
void CBPEXSourceProvider::BoostSleepEx(unsigned int nMilliseconds)
{
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
}
std::string CBPEXSourceProvider::FindPacketHead(const std::string& strPacket)
{
boost::smatch what;
boost::regex expression("0000[0-9]{4}");
boost::match_flag_type flags = boost::match_default;
std::string strPacketHead;
if (boost::regex_search(strPacket, what, expression, flags))
{
//std::cout << what.size() << std::endl;
for (size_t i = 0; i < what.size(); ++i)
{
if (what[i].matched)
{
strPacketHead = what[i];
//std::cout << what[i] << std::endl;
break;
}
}
}
return strPacketHead;
}
unsigned long long CBPEXSourceProvider::GetLocalTime()
{
// 这时候strTime里存放时间的格式是YYYYMMDDTHHMMSS,日期和时间用大写字母T隔开了
std::string timeFarmat = boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time());
timeFarmat.replace(timeFarmat.find('T'), 1, std::string(""));
unsigned long long timeValue = (unsigned long long)(std::stoull(timeFarmat.c_str()));
return timeValue;
}
std::string CBPEXSourceProvider::GetSystemTime()
{
time_t now_time;
now_time = time(NULL);
unsigned long long t = now_time;
t *= 1000;
char szSysTime[16] = {0};
sprintf(szSysTime, "%lld", t);
std::string strSysTime;
strSysTime = szSysTime;
return strSysTime;
}
std::string CBPEXSourceProvider::GetFormatTime(const std::string& strTimeStamp)
{
std::string strResult = "";
long long t = (long long)(atof(strTimeStamp.data()));
time_t now_time;
now_time = (t - t % 1000) / 1000;
struct tm* pTmLocal = localtime(&now_time);
if (NULL != pTmLocal)
{
char chTemp[64] = {0};
sprintf(chTemp, "%04d-%02d-%02d %02d:%02d:%02d",
pTmLocal->tm_year + 1900, pTmLocal->tm_mon + 1, pTmLocal->tm_mday,
pTmLocal->tm_hour, pTmLocal->tm_min, pTmLocal->tm_sec);
strResult = chTemp;
}
return strResult;
}
bool CBPEXSourceProvider::ParseXMLData(const std::string& strXML)
{
// 发送包的拼接
Stk::StockDetail* detail = new Stk::StockDetail();
detail->set_en_code("");
detail->set_seq_num(0);
detail->set_data_source_name(m_strHead);
TiXmlDocument docXml;
docXml.Parse(strXML.c_str());
TiXmlHandle docHandle(&docXml);
TiXmlHandle Root = docHandle.FirstChildElement("root");
std::string strDomain;
// 获取商品类名
strDomain = "prod_code";
TiXmlElement* pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
std::string strOrgCode;
strOrgCode = m_strHead + "@" + pNode->GetText();
detail->set_org_code(strOrgCode);
detail->set_own_code(strOrgCode);
// 获取交易日期时间
std::string strTradeTime;
strDomain = "quoteDate";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
strTradeTime = pNode->GetText();
strDomain = "quoteTime";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
strTradeTime += pNode->GetText();
replace_all_distinct(strTradeTime, ":", "");
detail->set_trade_time(std::stoull(strTradeTime.c_str()));
detail->set_local_time(GetLocalTime());
// 获取开盘价
strDomain = "open";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
unsigned int uTradePrice = 0u;
std::string strTmpPrice;
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_open_price(uTradePrice);
// 获取最高价
strDomain = "high";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_high_price(uTradePrice);
// 获取最低价
strDomain = "low";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_low_price(uTradePrice);
// 获取昨收价
strDomain = "close";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_pclose_price(uTradePrice);
// 获取买价
strDomain = "bid1";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_ask_price(uTradePrice);
// 获取卖价
strDomain = "ask1";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
//买价
detail->set_bid_price(uTradePrice);
//交易价格
detail->set_trade_price(uTradePrice);
// 获取成交量
strDomain = "volume";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stoi(strTmpPrice.data()));
detail->set_volume(uTradePrice);
CDataSourcePostControl::m_workQueue.push(detail);
//std::cout << detail->DebugString() << std::endl;
//WriteLogB(detail->DebugString());
return true;
}
std::string JStringToCString(JNIEnv* env, jstring jstr)
{
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize blen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
char* pstr = NULL;
std::string cstrcontent;
if (blen > 0)
{
pstr = new char[blen + 1];
memset(pstr, 0x00, blen + 1);
memcpy(pstr, ba, blen);
cstrcontent.append(pstr, blen);
delete [] pstr;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return cstrcontent;
}
jstring CharToJString(JNIEnv* env, const char* pch)
{
jclass strClass = env->FindClass("Ljava/lang/String;");
jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
jbyteArray bytes = env->NewByteArray(strlen(pch));
env->SetByteArrayRegion(bytes, 0, strlen(pch), (jbyte*)pch);
jstring encoding = env->NewStringUTF("utf-8");
return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}
std::string& trim(std::string& strtxt)
{
if (strtxt.empty())
{
return strtxt;
}
strtxt.erase(0, strtxt.find_first_not_of(' '));
strtxt.erase(strtxt.find_last_not_of(' ') + 1);
return strtxt;
}
string& replace_all_distinct(string& str, const string& old_value, const string& new_value)
{
for (string::size_type pos(0); pos != string::npos; pos += new_value.length())
{
if ((pos = str.find(old_value, pos)) != string::npos)
{
str.replace(pos, old_value.length(), new_value);
}
else
{
break;
}
}
return str;
}
#include "FXProtocol.pb.h"
#include "BPEX_MsgHeader.h"
#include "DataSourcePostControl.h"
#include "BPEX_SourceProvider.h"
#include <cryptopp/hex.h>
#include <cryptopp/default.h>
#include <cryptopp/filters.h>
#include <iomanip>
#include <sstream>
#include "tinyxml/tinyxml.h"
#include <boost/bind.hpp>
#include <boost/thread.hpp>
#include <boost/regex.hpp>
#include <boost/foreach.hpp>
#include <boost/algorithm/string/split.hpp>
#include <boost/date_time/posix_time/time_period.hpp>
#include <boost/date_time/posix_time/time_period.hpp>
#include <boost/date_time/posix_time/time_formatters.hpp>
#include <boost/date_time/posix_time/time_formatters.hpp>
std::string StringEncoderHex(const std::string& decoded, std::string& encoded)
{
CryptoPP::StringSource ss((byte*)decoded.data(), decoded.size(), true,
new CryptoPP::HexEncoder(
new CryptoPP::StringSink(encoded)
) // HexEncoder
); // StringSource
return encoded;
}
std::string HexDecodedString(const std::string& encoded, std::string& decoded)
{
CryptoPP::StringSource ss((byte*)encoded.data(), encoded.size(), true /*pumpAll*/,
new CryptoPP::HexDecoder(
new CryptoPP::StringSink(decoded)
) // HexDecoder
); // StringSource
return decoded;
}
//java与C++间的字符转换
jstring CharToJString(JNIEnv* env, const char* pch);
std::string JStringToCString(JNIEnv* env, jstring jstr);
//去空白
std::string& trim(std::string& strtxt);
//指定time_t类型的时间,格式化为YYYYMMDDHH24MISS型的字符串
void FormatTime(time_t time1, char* szTime)
{
struct tm tm1;
#ifdef WIN32
tm1 = *localtime(&time1);
#else
localtime_r(&time1, &tm1);
#endif
sprintf(szTime, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d",
tm1.tm_year + 1900, tm1.tm_mon + 1, tm1.tm_mday,
tm1.tm_hour, tm1.tm_min, tm1.tm_sec);
}
//void WriteLog(std::string strLog)
void WriteLog(const char* strLog)
{
FILE* fp = NULL;
static int ICOUNT = 1;
std::string strFile;
strFile = "./log/ReceiveDetail.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
std::string strLogContent;
strLogContent = strLog;
fwrite(strLogContent.data(), 1, strLogContent.size(), fp);
if (0 == (ICOUNT++ % 4096))
{
fwrite("\n", 1, 1, fp);
ICOUNT = 1;
}
fclose(fp);
}
void WriteLogReadHex(const string& strLog)
{
FILE* fp = NULL;
static int ICOUNT = 0;
std::string strFile;
strFile = "./log/ReceiveDetail_Read_Hex.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
std::string strLogContent;
strLogContent = strLog;
fwrite(strLogContent.data(), 1, strLogContent.size(), fp);
ICOUNT += strLogContent.size();
if (0 == (ICOUNT % 4096))
{
fwrite("\n", 1, 1, fp);
ICOUNT = 0;
}
fclose(fp);
}
void WriteLogParseHex(const string& strLog)
{
FILE* fp = NULL;
std::string strFile;
strFile = "./log/ReceiveDetail_Parse_Hex.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
std::string strLogContent;
strLogContent = strLog;
fwrite(strLogContent.data(), 1, strLogContent.size(), fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
void WriteLogB(std::string& strLog)
{
FILE* fp = NULL;
static int ICOUNT = 1;
std::string strFile;
strFile = "./log/ReceiveDetailB.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
//std::string strLogContent;
//strLogContent = strLog;
fwrite(strLog.data(), 1, strLog.size(), fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
void WriteLogD(const std::string& strLog)
{
FILE* fp = NULL;
static int ICOUNT = 1;
std::string strFile;
strFile = "./log/ReceiveDetailB.log";
if ((fp = fopen(strFile.c_str(), "a+")) == NULL)
{
fprintf(stderr, "fopen file error: %s\n\n", strFile.c_str());
return;
}
fwrite(strLog.data(), 1, strLog.size(), fp);
fwrite("\n", 1, 1, fp);
fclose(fp);
}
JavaVM* CBPEXSourceProvider::m_jvm = NULL;
JNIEnv* CBPEXSourceProvider::m_env = NULL;
HINSTANCE CBPEXSourceProvider::m_hInstance = NULL;
jclass CBPEXSourceProvider::m_cls = NULL;
std::string CBPEXSourceProvider::m_JVM_PATH("");
std::string CBPEXSourceProvider::m_JAR_PATH("");
CBPEXSourceProvider::CBPEXSourceProvider()
: m_mul(1000)
, m_strIpAddress("")
, m_strIpPort("")
, m_strHead("")
, m_strUserName("")
, m_strPassWord("")
, m_strRsaPublicKey("")
, m_bStop(false)
, m_changekey(true)
{
}
CBPEXSourceProvider::~CBPEXSourceProvider()
{
if (NULL != m_jvm)
{
//销毁虚拟机并释放动态库
m_jvm->DestroyJavaVM();
::FreeLibrary(m_hInstance);
}
}
bool CBPEXSourceProvider::InitConfig()
{
CIniConfigure iniconfig("DataSourcePort_BPEX.ini", "MAIN");
std::string strMul;
strMul = iniconfig.GetConfigString("MUL", "10000");
m_mul = std::stoi(strMul);
m_strIpAddress = iniconfig.GetConfigString("IP", "");
m_strIpPort = iniconfig.GetConfigString("PORT", "");
m_strHead = iniconfig.GetConfigString("HEAD", "");
m_strUserName = iniconfig.GetConfigString("USERNAME", "");
m_strPassWord = iniconfig.GetConfigString("PASSWORD", "");
m_strRsaPublicKey = iniconfig.GetConfigString("RSAPUBLICKEY", "");
if (m_strIpAddress == "" || m_strIpPort == "" || m_strHead == "" ||
m_strUserName == "" || m_strPassWord == "" || m_strRsaPublicKey == "")
{
return false;
}
m_JVM_PATH = iniconfig.GetConfigString("JVM_PATH", "");
m_JAR_PATH = iniconfig.GetConfigString("JAR_PATH", "");
//初始化JAVA虚拟机
if (true != InitJavaVM())
{
return false;
}
return true;
}
bool CBPEXSourceProvider::InitJavaVM()
{
//定义一个函数指针,下面用来指向JVM中的JNI_CreateJavaVM函数
typedef jint(WINAPI * PFunCreateJavaVM)(JavaVM**, void**, void*);
int res = -1;
JavaVMInitArgs vm_args;
JavaVMOption options[3];
JavaVM* jvm = NULL;
JNIEnv* env = NULL;
/*设置初始化参数*/
//disable JIT,这是JNI文档中的解释,具体意义不是很清楚 ,能取哪些值也不清楚。
//从JNI文档里给的示例代码中搬过来的
options[0].optionString = "-Djava.compiler=NONE";
//设置classpath,如果程序用到了第三方的JAR包,也可以在这里面包含进来
//options[1].optionString = "-Djava.class.path=./BpexQuote.jar";
char strJarPath[256] = {0};
sprintf(strJarPath, "-Djava.class.path=%s", m_JAR_PATH.c_str());
options[1].optionString = strJarPath;
//设置显示消息的类型,取值有gc、class和jni,如果一次取多个的话值之间用逗号格开,如-verbose:gc,class
//该参数可以用来观察C++调用JAVA的过程,设置该参数后,程序会在标准输出设备上打印调用的相关信息
options[2].optionString = "-verbose:NONE";
//设置版本号,版本号有JNI_VERSION_1_1,JNI_VERSION_1_2和JNI_VERSION_1_4
//选择一个根你安装的JRE版本最近的版本号即可,不过你的JRE版本一定要等于或者高于指定的版本号
vm_args.version = JNI_VERSION_1_8;
vm_args.nOptions = 3;
vm_args.options = options;
//该参数指定是否忽略非标准的参数,如果填JNI_FLASE,当遇到非标准参数时,JNI_CreateJavaVM会返回JNI_ERR
vm_args.ignoreUnrecognized = JNI_TRUE;
//加载JVM.DLL动态库
//std::string strJvmLib = "D:\\Program Files (x86)\\Java\\jdk1.8.0_51\\jre\\bin\\client\\jvm.dll";
std::string strJvmLib = m_JVM_PATH;
#ifdef _UNICODE
//格式转换问题
WCHAR wstrJvmLib[MAX_PATH] = {0};
//返回所需的短字符数组空间的个数
DWORD dwNum = MultiByteToWideChar(CP_ACP, 0, strJvmLib.data(), -1, NULL, 0);
MultiByteToWideChar(CP_ACP, 0, strJvmLib.data(), -1, wstrJvmLib, dwNum); // 开始转换
HINSTANCE hInstance = ::LoadLibrary(wstrJvmLib);
#else
HINSTANCE hInstance = ::LoadLibrary(strJvmLib.c_str());
#endif
if (hInstance == NULL)
{
return false;
}
//取得里面的JNI_CreateJavaVM函数指针
PFunCreateJavaVM funCreateJavaVM = (PFunCreateJavaVM)::GetProcAddress(hInstance, "JNI_CreateJavaVM");
//调用JNI_CreateJavaVM创建虚拟机
res = (*funCreateJavaVM)(&jvm, (void**)&env, &vm_args);
if (res < 0)
{
return false;
}
//查找类,返回JAVA类的CLASS对象
jclass cls = env->FindClass("com/ylink/outqut/QuoteLib");
if (NULL == cls)
{
return false;
}
m_hInstance = hInstance;
m_jvm = jvm;
m_env = env;
m_cls = cls ;
return true;
}
void CBPEXSourceProvider::Run()
{
if (InitConfig())
{
boost::thread thrst(boost::bind(&CBPEXSourceProvider::Start, this));
BoostSleep(5);
boost::thread thrde(boost::bind(&CBPEXSourceProvider::ProDeCryptData, this));
}
else
{
std::cout << "读取IP IP端口号 用户密码出错。" << std::endl;
}
return;
}
void CBPEXSourceProvider::Start()
{
if (false == Login())
{
lock_type lock(m_mutex);
m_bStop = true;
m_client.StopConnect();
return;
}
while (!m_bStop)
{
// 接受数据
if (!ReciveData())
{
std::cout << __LINE__ << "ReciveData false!" << std::endl;
break;
}
}
lock_type lock(m_mutex);
m_bStop = true;
return;
}
bool CBPEXSourceProvider::Login()
{
std::string strIpAddress;
std::string strIpPort;
strIpAddress = m_strIpAddress;
strIpPort = m_strIpPort;
m_client.StopConnect();
if (false == Connect(strIpAddress, strIpPort))
{
return false;
}
std::string strUserName = m_strUserName;
std::string strPassWord = m_strPassWord;
std::string strRsaPulicKey = m_strRsaPublicKey;
if (false == GetLoginCredentials(strUserName, strPassWord, strRsaPulicKey))
{
return false;
}
int nDataLen = 0;
int nWriteLen = 0;
nDataLen = m_strLoginCredentials.size();
// 发送登录信息
m_client.SetTimeout(60 * 1000);
nWriteLen = m_client.WriteData(m_strLoginCredentials.data(), nDataLen);
if (nWriteLen == -1)
{
return false;
}
lock_type lock(m_mutex);
m_changekey = true;
return true;
}
bool CBPEXSourceProvider::Connect(std::string strIpAddress, std::string strIpPort)
{
if (true == m_client.IsOpen())
{
return true;
}
m_client.StopConnect();
if (false == m_client.StartConnect(strIpAddress, strIpPort))
{
return false;
}
return true;
}
bool CBPEXSourceProvider::GetLoginCredentials(const std::string& username, const std::string& password, const std::string& rsapulickey)
{
JNIEnv* env = NULL;
jclass cls = NULL;
jobject obj = NULL;
if (NULL != m_env && NULL != m_cls)
{
cls = m_cls;
//JNIEnv和jobject对象都不能跨线程使用
m_jvm->AttachCurrentThread((void**)&env, NULL);
//obj = env->NewGlobalRef(m_obj); //创建一个全局变量
//m_obj = obj;
}
else
{
return false;
}
//根据类的CLASS对象获取该类的实例
obj = env->AllocObject(cls);
if (NULL == obj)
{
return false;
}
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
jmethodID mid = env->GetMethodID(cls, "GetLoginCredentials", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;");
jstring strjUserName;
jstring strjPassWord;
jstring strjRsaPulicKey;
strjUserName = CharToJString(env, username.c_str());
strjPassWord = CharToJString(env, password.c_str());
strjRsaPulicKey = CharToJString(env, rsapulickey.c_str());
jstring strjLoginCredential;
strjLoginCredential = (jstring)env->CallObjectMethod(obj, mid, strjUserName, strjPassWord, strjRsaPulicKey);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = env->ExceptionOccurred();
if (excp)
{
jclass cls = env->GetObjectClass(excp);
env->ExceptionClear();
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring msg = (jstring) env->CallObjectMethod(excp, mid);
std::cout << JStringToCString(env, msg) << std::endl;
env->ExceptionClear();
}
std::string strLoginCredential;
strLoginCredential = JStringToCString(env, strjLoginCredential);
//std::cout << __LINE__ << ": " << strLoginCredential << std::endl;
m_strLoginCredentials.clear();
std::stringstream sstr;
int a = 5;
sstr << setw(8) << setfill('0') << strLoginCredential.size() ;
m_strLoginCredentials = sstr.str();
m_strLoginCredentials += strLoginCredential;
//获取KEY
jstring strjKey;
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
mid = env->GetMethodID(cls, "GetDEesKey", "()Ljava/lang/String;");
strjKey = (jstring)env->CallObjectMethod(obj, mid);
m_strjKey = strjKey;
std::string strKey;
strKey = JStringToCString(env, strjKey);
//std::cout << __LINE__ << ": " << strKey << std::endl;
m_jvm->DetachCurrentThread();
//WriteLog(strKey.c_str());
//WriteLog(strLoginCredential.c_str());
return true;
}
bool CBPEXSourceProvider::ReciveData()
{
// 读取报文体
size_t nDataLen = 2;
int nRedDataLen = 0;
char szDataStream[1024] = {0};
int count = 1;
while (!m_bStop)
{
memset(szDataStream, 0x00, sizeof(szDataStream));
m_client.SetTimeout(300 * 1000);
nRedDataLen = m_client.ReadData(szDataStream, nDataLen);
//WriteLog(szDataStream);
std::string strHex;
StringEncoderHex(szDataStream, strHex);
WriteLogReadHex(strHex);
if (-1 == nRedDataLen)
{
if (false == Login())
{
break;
}
continue;
}
m_mutex.lock();
m_strQuoteDataStream.append(szDataStream, nRedDataLen);
if (m_strQuoteDataStream.size() > 26)
{
m_cond_proc.notify_one();
}
m_mutex.unlock();
}
m_cond_proc.notify_one();
return false;
}
bool CBPEXSourceProvider::ProDeCryptData()
{
std::string strQuoteDataStream;
JNIEnv* env = NULL;
jclass cls;
jobject obj;
jmethodID des_mid;
jmethodID changekey_mid;
if (NULL != m_env && NULL != m_cls)
{
//JNIEnv和jobject对象都不能跨线程使用
m_jvm->AttachCurrentThread((void**)&env, NULL);
cls = m_cls;
}
else
{
return false;
}
//根据类的CLASS对象获取该类的实例
obj = env->AllocObject(cls);
if (NULL == obj)
{
return false;
}
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
changekey_mid = env->GetMethodID(cls, "SetDesKey", "(Ljava/lang/String;)V");
//获取类中的方法,最后一个参数是方法的签名,通过javap -s -p 文件名可以获得
des_mid = env->GetMethodID(cls, "DecryptPackets", "(Ljava/lang/String;)Ljava/lang/String;");
while (!m_bStop)
{
std::string strCiphertext;
if (m_changekey == true)
{
jstring strjKey;
strjKey = m_strjKey;
env->CallObjectMethod(obj, changekey_mid, strjKey);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = env->ExceptionOccurred();
if (excp)
{
jclass cls = env->GetObjectClass(excp);
env->ExceptionClear();
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring msg = (jstring) env->CallObjectMethod(excp, mid);
std::cout << JStringToCString(env, msg) << std::endl;
env->ExceptionClear();
return false;
}
lock_type lock(m_mutex);
m_changekey = false;
}
m_mutex.lock();
if (strQuoteDataStream.size() < 26)
{
m_cond_proc.wait(m_mutex);
}
if (m_strQuoteDataStream.size() >= 2)
{
strQuoteDataStream.append(m_strQuoteDataStream);
m_strQuoteDataStream.clear();
}
m_mutex.unlock();
//获取报文头
std::string strHead = FindPacketHead(strQuoteDataStream);
//对获取到包进行分析处理
if (strQuoteDataStream.size() < 26 || "" == strHead)
{
continue;
}
int iStartPos = 0;
int iEndPos = 0;
//获取第一个报文头的起始位置
if (std::string::npos != strQuoteDataStream.find(strHead, iStartPos))
{
iStartPos = strQuoteDataStream.find(strHead, iStartPos);
}
//对一个报文的长度
unsigned int iPacketLen = stoi(strHead);
if ((iStartPos + (8 + 2) + iPacketLen) > strQuoteDataStream.size())
{
continue;
}
//获取第二个报文头的位置
std::string strValue;
strValue = strQuoteDataStream.substr(iStartPos + 8 + iPacketLen);
strHead = FindPacketHead(strValue);
if ("" == strHead)
{
continue;
}
//获取第一个报文的结束位置
if (std::string::npos != strQuoteDataStream.find(strHead, iStartPos + 8 + iPacketLen))
{
iEndPos = strQuoteDataStream.find(strHead, iStartPos + 8 + iPacketLen);
}
strValue.clear();
strValue = strQuoteDataStream.substr(iStartPos, iEndPos - iStartPos);
std::string strTempValue;
strTempValue = strQuoteDataStream.substr(iEndPos);
strQuoteDataStream.clear();
strQuoteDataStream = strTempValue;
//std::cout << strValue << std::endl;
//WriteLogB(strValue);
std::string strHex;
StringEncoderHex(strValue, strHex);
WriteLogParseHex(strHex);
//心跳报文: 00000018ConnectTestSucceed
if (std::string::npos != strValue.find("ConnectTestSucceed"))
{
continue;
}
jstring strjValue;
strjValue = CharToJString(env, strValue.c_str());
jstring strjPlainText;
strjPlainText = (jstring)env->CallObjectMethod(obj, des_mid, strjValue);
//获取异常信息
string exceptionInfo = "";
jthrowable excp = 0;
excp = env->ExceptionOccurred();
if (excp)
{
jclass cls = env->GetObjectClass(excp);
env->ExceptionClear();
jmethodID mid = env->GetMethodID(cls, "toString", "()Ljava/lang/String;");
jstring msg = (jstring) env->CallObjectMethod(excp, mid);
std::cout << JStringToCString(env, msg) << std::endl;
env->ExceptionClear();
WriteLogB(JStringToCString(env, msg));
continue;
}
std::string strPlainText;
strPlainText = JStringToCString(env, strjPlainText);
ParseXMLData(strPlainText);
}
lock_type lock(m_mutex);
m_bStop = true;
m_jvm->DetachCurrentThread();
return true;
}
void CBPEXSourceProvider::BoostSleep(unsigned int nSeconds)
{
boost::xtime xt;
boost::xtime_get(&xt, boost::TIME_UTC_);
xt.sec += nSeconds;
boost::thread::sleep(xt);
}
void CBPEXSourceProvider::BoostSleepEx(unsigned int nMilliseconds)
{
boost::this_thread::sleep(boost::posix_time::milliseconds(200));
}
std::string CBPEXSourceProvider::FindPacketHead(const std::string& strPacket)
{
boost::smatch what;
boost::regex expression("0000[0-9]{4}");
boost::match_flag_type flags = boost::match_default;
std::string strPacketHead;
if (boost::regex_search(strPacket, what, expression, flags))
{
//std::cout << what.size() << std::endl;
for (size_t i = 0; i < what.size(); ++i)
{
if (what[i].matched)
{
strPacketHead = what[i];
//std::cout << what[i] << std::endl;
break;
}
}
}
return strPacketHead;
}
unsigned long long CBPEXSourceProvider::GetLocalTime()
{
// 这时候strTime里存放时间的格式是YYYYMMDDTHHMMSS,日期和时间用大写字母T隔开了
std::string timeFarmat = boost::posix_time::to_iso_string(boost::posix_time::second_clock::local_time());
timeFarmat.replace(timeFarmat.find('T'), 1, std::string(""));
unsigned long long timeValue = (unsigned long long)(std::stoull(timeFarmat.c_str()));
return timeValue;
}
std::string CBPEXSourceProvider::GetSystemTime()
{
time_t now_time;
now_time = time(NULL);
unsigned long long t = now_time;
t *= 1000;
char szSysTime[16] = {0};
sprintf(szSysTime, "%lld", t);
std::string strSysTime;
strSysTime = szSysTime;
return strSysTime;
}
std::string CBPEXSourceProvider::GetFormatTime(const std::string& strTimeStamp)
{
std::string strResult = "";
long long t = (long long)(atof(strTimeStamp.data()));
time_t now_time;
now_time = (t - t % 1000) / 1000;
struct tm* pTmLocal = localtime(&now_time);
if (NULL != pTmLocal)
{
char chTemp[64] = {0};
sprintf(chTemp, "%04d-%02d-%02d %02d:%02d:%02d",
pTmLocal->tm_year + 1900, pTmLocal->tm_mon + 1, pTmLocal->tm_mday,
pTmLocal->tm_hour, pTmLocal->tm_min, pTmLocal->tm_sec);
strResult = chTemp;
}
return strResult;
}
bool CBPEXSourceProvider::ParseXMLData(const std::string& strXML)
{
// 发送包的拼接
Stk::StockDetail* detail = new Stk::StockDetail();
detail->set_en_code("");
detail->set_seq_num(0);
detail->set_data_source_name(m_strHead);
TiXmlDocument docXml;
docXml.Parse(strXML.c_str());
TiXmlHandle docHandle(&docXml);
TiXmlHandle Root = docHandle.FirstChildElement("root");
std::string strDomain;
// 获取商品类名
strDomain = "prod_code";
TiXmlElement* pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
std::string strOrgCode;
strOrgCode = m_strHead + "@" + pNode->GetText();
detail->set_org_code(strOrgCode);
detail->set_own_code(strOrgCode);
// 获取交易日期时间
std::string strTradeTime;
strDomain = "quoteDate";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
strTradeTime = pNode->GetText();
strDomain = "quoteTime";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
strTradeTime += pNode->GetText();
replace_all_distinct(strTradeTime, ":", "");
detail->set_trade_time(std::stoull(strTradeTime.c_str()));
detail->set_local_time(GetLocalTime());
// 获取开盘价
strDomain = "open";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
unsigned int uTradePrice = 0u;
std::string strTmpPrice;
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_open_price(uTradePrice);
// 获取最高价
strDomain = "high";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_high_price(uTradePrice);
// 获取最低价
strDomain = "low";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_low_price(uTradePrice);
// 获取昨收价
strDomain = "close";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_pclose_price(uTradePrice);
// 获取买价
strDomain = "bid1";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
detail->set_ask_price(uTradePrice);
// 获取卖价
strDomain = "ask1";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stof(strTmpPrice.data()) * m_mul);
//买价
detail->set_bid_price(uTradePrice);
//交易价格
detail->set_trade_price(uTradePrice);
// 获取成交量
strDomain = "volume";
pNode = Root.FirstChildElement(strDomain.c_str()).ToElement();
if (NULL == pNode)
{
return false;
}
uTradePrice = 0u;
strTmpPrice.clear();
strTmpPrice = pNode->GetText();
trim(strTmpPrice);
uTradePrice = (unsigned int)(std::stoi(strTmpPrice.data()));
detail->set_volume(uTradePrice);
CDataSourcePostControl::m_workQueue.push(detail);
//std::cout << detail->DebugString() << std::endl;
//WriteLogB(detail->DebugString());
return true;
}
std::string JStringToCString(JNIEnv* env, jstring jstr)
{
jclass clsstring = env->FindClass("java/lang/String");
jstring strencode = env->NewStringUTF("utf-8");
jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
jbyteArray barr = (jbyteArray)env->CallObjectMethod(jstr, mid, strencode);
jsize blen = env->GetArrayLength(barr);
jbyte* ba = env->GetByteArrayElements(barr, JNI_FALSE);
char* pstr = NULL;
std::string cstrcontent;
if (blen > 0)
{
pstr = new char[blen + 1];
memset(pstr, 0x00, blen + 1);
memcpy(pstr, ba, blen);
cstrcontent.append(pstr, blen);
delete [] pstr;
}
env->ReleaseByteArrayElements(barr, ba, 0);
return cstrcontent;
}
jstring CharToJString(JNIEnv* env, const char* pch)
{
jclass strClass = env->FindClass("Ljava/lang/String;");
jmethodID ctorID = env->GetMethodID(strClass, "<init>", "([BLjava/lang/String;)V");
jbyteArray bytes = env->NewByteArray(strlen(pch));
env->SetByteArrayRegion(bytes, 0, strlen(pch), (jbyte*)pch);
jstring encoding = env->NewStringUTF("utf-8");
return (jstring)env->NewObject(strClass, ctorID, bytes, encoding);
}
std::string& trim(std::string& strtxt)
{
if (strtxt.empty())
{
return strtxt;
}
strtxt.erase(0, strtxt.find_first_not_of(' '));
strtxt.erase(strtxt.find_last_not_of(' ') + 1);
return strtxt;
}
string& replace_all_distinct(string& str, const string& old_value, const string& new_value)
{
for (string::size_type pos(0); pos != string::npos; pos += new_value.length())
{
if ((pos = str.find(old_value, pos)) != string::npos)
{
str.replace(pos, old_value.length(), new_value);
}
else
{
break;
}
}
return str;
}
相关文章推荐
- 关于vs2005、vs2008和vs2010项目互转的总结
- vs2010根据字符串内容添加断点的方法介绍
- 在vs2010中调试javascript代码方法
- VS2010写的程序在自己电脑可以运行、其他电脑上不能运行的解决方案
- VS2010 C++ 配置优化方案
- 使用VS2010创建MFC ActiveX工程项目
- 使用VS2010 C#开发ActiveX控件(下),完整代码打包下载
- 使用VS2010 C#开发ActiveX控件(上)
- 解析VS2010利用VS.PHP插件调试PHP的方法
- win7系统下 vs2010 调式就关闭要重启处理方法
- VS2010新建站点发布并访问步骤详解
- VS2010、VS2008等项目的默认浏览器修改方法(图文)
- 如何在VS2012中查看IL代码
- VS2010/MFC编程入门之前言
- VS2010/MFC编程入门之二(利用MFC向导生成单文档应用程序框架)
- VS2010/MFC编程入门之三(VS2010应用程序工程中文件的组成结构)
- VS2010/MFC编程入门之四(MFC应用程序框架分析)
- VS2010/MFC编程入门之五(MFC消息映射机制概述)
- VS2010/MFC编程入门之六(对话框:创建对话框模板和修改对话框属性)
- VS2010/MFC编程入门之七(对话框:为对话框添加控件)