thread_local MYSQL* thread_mysql_conn = nullptr;
struct stkvec {
char stkcode[7];
char stkname[21];
};
std::string wstringToString(const std::wstring& wstr) {
if (wstr.empty()) return std::string();
int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
std::string strTo(size_needed, 0);
WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
return strTo;
}
std::vector<stkvec> stkvecs;
std::wstring utf82wstring(const std::string& str)
{
if (str.empty()) return std::wstring();
int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
std::wstring wstrTo(size_needed, 0);
MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
return wstrTo;
}
bool FetchDataVec() {
HANDLE hMapFile = OpenFileMapping(FILE_MAP_READ, FALSE, L"Global\\MySharedMemory");
if (hMapFile == NULL) {
std::cerr << "Error opening shared memory: " << GetLastError() << std::endl;
return false;
}
LPVOID pBuf = MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0);
if (pBuf == NULL) {
std::cerr << "Error mapping view of file: " << GetLastError() << std::endl;
CloseHandle(hMapFile);
return false;
}
char* dataPtr = static_cast<char*>(pBuf);
int recordCount = *reinterpret_cast<int*>(dataPtr);
dataPtr += sizeof(int);
const int RECORD_SIZE = 6 + 20;
if (recordCount <= 0) {
std::cerr << "Invalid record count: " << recordCount << std::endl;
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return false;
}
stkvecs.clear();
for (int i = 0; i < recordCount; ++i) {
stkvec vec;
// 读取 stkcode(6 字节)
memcpy(vec.stkcode, dataPtr, 6);
vec.stkcode[6] = '\0';
dataPtr += 6;
// 读取 stkname(20 字节)
memcpy(vec.stkname, dataPtr, 20);
vec.stkname[20] = '\0';
dataPtr += 20;
// 将 vec 添加到 stkvecs 中
stkvecs.push_back(vec);
}
UnmapViewOfFile(pBuf);
CloseHandle(hMapFile);
return true;
}
std::string cstrToStdString(const char* cstr, size_t max_len) {
return std::string(cstr, strnlen(cstr, max_len));
}
std::string cleanName(const std::string& name) {
std::string cleaned = std::regex_replace(name, std::regex("\\s+"), " ");
cleaned = std::regex_replace(cleaned, std::regex("^\\s+|\\s+$"), "");
return cleaned;
}
void cleanup_thread_mysql_connection() {
if (thread_mysql_conn) {
mysql_close(thread_mysql_conn);
thread_mysql_conn = nullptr;
}
}
std::string escapeRegex(const std::string& str) {
return std::regex_replace(str, std::regex(R"([\^$.|?*+(){}$$])"), R"(\$&)");
}
std::string preprocessText(const std::string& text) {
std::string cleaned = std::regex_replace(text, std::regex("<[^>]*>"), "");
cleaned = std::regex_replace(cleaned, std::regex(" "), " ");
cleaned = std::regex_replace(cleaned, std::regex("\\s+"), " ");
cleaned = std::regex_replace(cleaned, std::regex("^\\s+|\\s+$"), "");
return cleaned;
}
std::vector<std::string> findMatchesWithRegex(const std::vector<stkvec>& stkvecs, const std::string& text) {
std::vector<std::string> matches;
std::string pattern;
for (const auto& vec : stkvecs) {
std::string stkname_str = cstrToStdString(vec.stkname, sizeof(vec.stkname)); // 转换为 std::string
if (!stkname_str.empty()) {
std::string cleaned_name = cleanName(stkname_str);
if (!cleaned_name.empty()) {
if (!pattern.empty()) pattern += "|";
pattern += escapeRegex(cleaned_name);
}
}
}
try {
std::string processed_text = preprocessText(text);
std::regex re(pattern, std::regex_constants::icase);
auto words_begin = std::sregex_iterator(processed_text.begin(), processed_text.end(), re);
auto words_end = std::sregex_iterator();
for (std::sregex_iterator i = words_begin; i != words_end; ++i) {
std::smatch match = *i;
std::string matched_str = match.str();
auto it = std::find_if(stkvecs.begin(), stkvecs.end(), [&matched_str](const stkvec& vec) {
std::string stkname_str = cstrToStdString(vec.stkname, sizeof(vec.stkname));
return cleanName(stkname_str) == matched_str;
});
if (it != stkvecs.end()) {
std::string stkcode_str = cstrToStdString(it->stkcode, sizeof(it->stkcode));
matches.push_back(stkcode_str);
//std::cout << "Found match for: " << matched_str << " -> stkcode: " << stkcode_str << std::endl;
}
else {
std::cout << "No match found for: " << matched_str << std::endl;
}
}
std::cout << "Found " << matches.size() << " matches." << std::endl;
}
catch (const std::regex_error& e) {
std::cerr << "Regex error: " << e.what() << std::endl;
}
return matches;
}
std::string extractJsonField(const std::string& jsonStr, const std::string& field);
//MYSQL* global_mysql_conn = nullptr;
using namespace std;
bool init_thread_mysql_connection(const std::string& host, const std::string& user, const std::string& passwd, const std::string& db, int port) {
printf("Initializing MySQL connection to %s:%d...\n", host.c_str(), port);
MYSQL* conn = mysql_init(nullptr);
if (!conn) {
fprintf(stderr, "Failed to initialize MySQL connection.\n");
return false;
}
if (!mysql_real_connect(conn, host.c_str(), user.c_str(), passwd.c_str(), db.c_str(), port, nullptr, 0)) {
fprintf(stderr, "Failed to connect to MySQL: %s\n", mysql_error(conn));
mysql_close(conn);
return false;
}
printf("MySQL connection initialized successfully.\n");
thread_mysql_conn = conn;
return true;
}
bool IsValidFloat(float fval) {
if (std::isnan(fval)) {
return false;
}
if (std::isinf(fval)) {
// fval is either positive or negative infinity
return false;
}
return true;
}
LPTDXDAT2 FetchDataNameFromMySQL(MYSQL* conn, const std::string& stkcode) {
MYSQL_RES* res = nullptr;
MYSQL_ROW row;
LPTDXDAT2 data = nullptr;
if (conn == nullptr) {
fprintf(stderr, "0000Connection is null. Reinitializing...\n");
if (!init_thread_mysql_connection("localhost", "admin", "Zls_[20]", "stock", 3306)){
fprintf(stderr, "-------1111Connection is null. Reinitializing...\n");
return nullptr;
}
}
mysql_query(conn, "SET NAMES 'utf8mb4'");
std::setlocale(LC_ALL, "zh_CN.UTF-8");
mysql_options(conn, MYSQL_SET_CHARSET_NAME, "utf8mb4"); //必须使用utf8, 原因不知道
if (mysql_set_character_set(conn, "utf8") != 0) {
std::cerr << "Error setting character set to utf8: " << mysql_error(conn) << std::endl;
}
char query[256];
snprintf(query, sizeof(query), "SELECT stknew,roe,mgsy,score,height,c2exp12,c2exp50,stkname,stkcode,c2exp12wk,c2exp50wk,seasonratio FROM fxj WHERE stkcode='%s'", stkcode.c_str());
if (mysql_query(conn, query)) {
fprintf(stderr, "2 SELECT query error: %s\n", mysql_error(conn));
mysql_close(conn);
return nullptr;
}
res = mysql_store_result(conn);
if (res) {
if ((row = mysql_fetch_row(res)) != NULL) {
// 分配内存给data
data = (LPTDXDAT2)calloc(1, sizeof(TDXDAT2));
if (!data) {
fprintf(stderr, "Memory allocation failed\n");
mysql_free_result(res);
mysql_close(conn);
return nullptr;
}
data->stknew = atof(row[0]);
data->roe = atof(row[1]);
data->mgsy = atof(row[2]);
data->score = atoi(row[3]);
data->height = atoi(row[4]);
data->c2exp12 = atoi(row[5]);
data->c2exp50 = atoi(row[6]);
data->c2exp12wk = atoi(row[9]);
data->c2exp50wk = atoi(row[10]);
data->seasonratio = atof(row[11]);
data->stkname = row[7] ? std::string(row[7]) : ""; // 使用std::string构造函数进行转换
data->stkcode = row[8] ? std::string(row[8]) : "";
}
else {
printf("No rows returned for stkname: %s\n", stkcode.c_str());
}
mysql_free_result(res);
}
return data;
}
LPTDXDAT2 FetchDataFromMySQL(MYSQL* conn, const std::string& stkcode) {
MYSQL_RES* res = nullptr;
MYSQL_ROW row;
LPTDXDAT2 data = nullptr;
if (conn == NULL) {
fprintf(stderr, "Connection is 22null\n");
return nullptr;
}
std::setlocale(LC_ALL, "zh_CN.UTF-8");
mysql_options(conn, MYSQL_SET_CHARSET_NAME, "utf8"); //必须使用utf8, 原因不知道
if (mysql_set_character_set(conn, "utf8") != 0) {
std::cerr << "Error setting character set to utf8: " << mysql_error(conn) << std::endl;
}
char query[256];
snprintf(query, sizeof(query), "SELECT stknew,roe,mgsy,score,height,c2exp12,c2exp50 FROM fxj WHERE stkcode='%s'", stkcode.c_str());
if (mysql_query(conn, query)) {
fprintf(stderr, "1 SELECT query error: %s\n", mysql_error(conn));
mysql_close(conn);
return nullptr;
}
res = mysql_store_result(conn);
if (res) {
if ((row = mysql_fetch_row(res)) != NULL) {
// 分配内存给data
data = (LPTDXDAT2)calloc(1, sizeof(TDXDAT2));
if (!data) {
fprintf(stderr, "Memory allocation failed\n");
mysql_free_result(res);
mysql_close(conn);
return nullptr;
}
// 设置stkcode
data->stkcode = stkcode;
data->stkname = ""; // 假设没有从数据库获取stkname
data->stknew = atof(row[0]);
data->roe = atof(row[1]);
data->mgsy = atof(row[2]);
data->score = atoi(row[3]);
data->height = atoi(row[4]);
data->c2exp12 = atoi(row[5]);
data->c2exp50 = atoi(row[6]);
}
else {
printf("No rows returned for stkcode: %s\n", stkcode.c_str());
}
mysql_free_result(res);
}
mysql_close(conn);
return data;
}
void init_openssl() {
SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
}
void cleanup_openssl() {
EVP_cleanup();
}
SSL_CTX* create_context() {
const SSL_METHOD* method;
SSL_CTX* ctx;
method = TLS_server_method();
ctx = SSL_CTX_new(method);
if (!ctx) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
return ctx;
}
void parseHtmlTableToStruct(const char* fileName, std::vector<TDXDAT2>& dataOut)
{
pugi::xml_document doc;
if (!doc.load_file(fileName)) {
std::cerr << "Failed to load file: " << fileName << std::endl;
return;
}
pugi::xml_node table = doc.child("html").child("body").child("table");
for (pugi::xml_node row : table.children("tr"))
{
// 跳过表头
if (std::string(row.child_value("th")) == "stkcode") continue;
TDXDAT2 data;
int colIndex = 0;
for (pugi::xml_node cell : row.children("td"))
{
const char* text = cell.child_value();
switch (colIndex++)
{
case 0: data.stkcode = text; break;
case 1: data.stkname = text; break;
case 2: data.stknew = std::stof(text); break;
case 3: data.roe = std::stof(text); break;
case 4: data.mgsy = std::stof(text); break; // 注意: 这里可能需要调整类型
case 5: data.score = std::stoi(text); break;
case 6: data.height = std::stoi(text); break;
case 7: data.c2exp12 = std::stoi(text); break; // 注意: 这里可能需要调整类型
case 8: data.c2exp50 = std::stoi(text); break; // 注意: 这里可能需要调整类型
}
}
dataOut.push_back(data);
}
}
void configure_context(SSL_CTX* ctx) {
std::ifstream certFile("C:\\sys\\cert.pem", std::ios::binary);
if (!certFile.is_open()) {
std::cerr << "Failed to open certificate file." << std::endl;
return;
}
std::cout << "Successfully opened certificate file." << std::endl;
SSL_CTX_set_ecdh_auto(ctx, 1);
if (SSL_CTX_use_certificate_file(ctx, "C:\\sys\\cert.pem", SSL_FILETYPE_PEM) <= 0) {
// 创建一个内存 BIO 来捕获错误信息
BIO* bio = BIO_new(BIO_s_mem());
if (bio != nullptr) {
ERR_print_errors(bio); // 将错误信息打印到 BIO
// 从 BIO 中读取数据并写入字符串流
char buffer[1024];
std::ostringstream oss;
int len;
while ((len = BIO_read(bio, buffer, sizeof(buffer))) > 0) {
oss.write(buffer, len);
}
BIO_free(bio);
std::ofstream logFile("c:\\sys\\error.log", std::ios::app);
if (logFile.is_open()) {
if (logFile.fail()) {
std::cerr << "Log file open failed with failbit set." << std::endl;
}
if (logFile.bad()) {
std::cerr << "Log file open failed with badbit set." << std::endl;
}
logFile << oss.str(); // 将错误信息写入日志文件
logFile << "Failed to load certificate file.\n";
logFile.close();
}
else {
std::cerr << "Failed to open error log file." << std::endl;
}
}
else {
std::cerr << "Failed to create BIO for error logging." << std::endl;
}
}
if (SSL_CTX_use_PrivateKey_file(ctx, "C:\\sys\\key.pem", SSL_FILETYPE_PEM) <= 0) {
ERR_print_errors_fp(stderr);
exit(EXIT_FAILURE);
}
}
void saveToJson1(const char* fileName, std::vector<std::vector<std::string>>& data)
{
std::ofstream outFile(fileName);
if (!outFile.is_open())
{
std::cout << "文件:'" << fileName << "' 打开失败,请确认文件是否被占用。" << std::endl;
return;
}
std::vector<std::string> title = data[0];
outFile << "[" << std::endl;
for (size_t row = 1; row < data.size(); row++)
{
outFile << "{" << std::endl;
for (size_t col = 0; col < data[row].size(); col++)
{
outFile << title[col] << ":" << data[row][col];
if (col < data[row].size() - 1)
{
outFile << ",";
}
outFile << std::endl;
}
if (row < data.size() - 1)
{
outFile << "}," << std::endl;
}
else
{
outFile << "}" << std::endl;
}
}
outFile << "]" << std::endl;
outFile.close();
}
std::string saveToJson(std::vector<std::vector<std::string>>& data)
{
std::ostringstream jsonString;
/// data的第0行是标题,所以从第一行开始
if (data.empty()) {
return "{}"; // 或者其它处理空数据的方式
}
std::vector<std::string> title = data[0];
jsonString << "[" << std::endl;
for (size_t row = 1; row < data.size(); row++)
{
jsonString << "{" << std::endl;
for (size_t col = 0; col < data[row].size(); col++)
{
jsonString << "\"" << title[col] << "\": \"" << data[row][col] << "\"";
if (col < data[row].size() - 1)
{
jsonString << ",";
}
jsonString << std::endl;
}
if (row < data.size() - 1)
{
jsonString << "}," << std::endl;
}
else
{
jsonString << "}" << std::endl;
}
}
jsonString << "]" << std::endl;
return jsonString.str();
}
std::string generateHtmlFromLstData(const std::vector<TDXDAT2>& lstData) {
std::stringstream ss;
ss << "<html><head><meta charset='UTF-8'></head><body><table>";
ss << "<thead><tr>"
<< "<th width='10%'>Code</th>"
<< "<th width='10%'>Name</th>"
<< "<th width='10%'>New</th>"
<< "<th width='10%'>ROE</th>"
<< "<th width='10%'>MGSY</th>"
<< "<th width='10%'>Score</th>"
<< "<th width='10%'>Height</th>"
<< "<th width='10%'>ExpMA12</th>"
<< "<th width='10%'>ExpMA50</th>"
<< "<th width='10%'>ExpMA12wk</th>"
<< "<th width='10%'>ExpMA50wk</th>"
<< "<th width='10%'>seasonratio</th>"
<< "</tr></thead><tbody>";
for (const auto& data : lstData) {
ss << "<tr>"
<< "<td>" << data.stkcode << "</td>"
<< "<td>" << data.stkname << "</td>"
<< "<td>" << data.stknew << "</td>"
<< "<td>" << data.roe << "</td>"
<< "<td>" << data.mgsy << "</td>"
<< "<td>" << data.score << "</td>"
<< "<td>" << data.height << "</td>"
<< "<td>" << data.c2exp12 << "</td>"
<< "<td>" << data.c2exp50 << "</td>"
<< "<td>" << data.c2exp12wk << "</td>"
<< "<td>" << data.c2exp50wk << "</td>"
<< "<td>" << data.seasonratio << "</td>"
<< "</tr>";
}
ss << "</tbody></table></body></html>";
return ss.str();
}
std::string removeHtmlTags(const std::string& html) {
std::regex tag_re("<[^>]+>"); // 匹配HTML标签的正则表达式
return std::regex_replace(html, tag_re, ""); // 替换掉所有的HTML标签
}
std::string handleRequest2(const std::string& method, const std::string& uri, const std::string& body, std::vector<TDXDAT2>& lstData) {
static bool isInit = false;
if (!isInit) {
if (!init_thread_mysql_connection("localhost", "admin", "Zls99", "stock", 3306)) {
return "HTTP/1.1 500 Internal Server Error\r\nContent-Type: text/plain; charset=utf-8\r\n\r\nFailed to initialize MySQL connection.";
}
isInit = true;
}
std::unordered_map<std::string, std::string> headers;
std::string responseContent;
int statusCode = 404;
if (method == "GET") {
if (uri == "/min") {
std::ifstream file("c:\\sys\\min.txt");
if (file.is_open()) {
statusCode = 200;
std::cout << "Handling " << method << " request for URI: " << uri << std::endl;
std::stringstream buffer;
buffer << file.rdbuf();
responseContent = "<html><body><p><span style=\"font-size: 12px;\">" + buffer.str() + "</span></p></body></html>";
file.close();
headers["Content-Type"] = "text/plain; charset=utf-8";
}
else {
statusCode = 404;
responseContent = "<html><body><h1>404 Not Found</h1></body></html>";
headers["Content-Type"] = "text/html; charset=utf-8";
}
}
else
{
statusCode = 404;
responseContent = "<html><body><h1>404 Not Found</h1></body></html>";
headers["Content-Type"] = "text/html; charset=utf-8";
}
}
else if (method == "POST") {
std::string dataIdStr = extractJsonField(body, "dataId");
int dataId = std::stoi(dataIdStr);
std::string sqlresult = "";
bool brr = getMysqlHtml(dataId, sqlresult);
if (brr) {
std::string plain_text = removeHtmlTags(sqlresult);
std::vector<std::string> matchedNames = findMatchesWithRegex(stkvecs, plain_text);
if (matchedNames.size() == 0)
{
goto POSTFINAL;
}
for (const auto& name : matchedNames) { //stkcode
if (name.empty())
{
continue;
}
TDXDAT2 data;
data.stkcode = name;
data.stknew = 0;
data.roe = 0;
data.mgsy = 0;
data.score = 0;
data.height = 0;
data.c2exp12 = 0;
data.c2exp50 = 0;
data.c2exp12wk = 0;
data.c2exp50wk = 0;
data.seasonratio = 0;
lstData.push_back(data);
}
for (size_t i = 0; i < lstData.size(); ++i) {
LPTDXDAT2 data = FetchDataNameFromMySQL(thread_mysql_conn, lstData[i].stkcode);
if (!data)
{
goto POSTFINAL;
}
lstData[i].stkname = data->stkname;
lstData[i].stknew = data->stknew;
lstData[i].mgsy = data->mgsy;
lstData[i].roe = data->roe;
lstData[i].height = data->height;
lstData[i].score = data->score;
lstData[i].c2exp12 = data->c2exp12;
lstData[i].c2exp50 = data->c2exp50;
lstData[i].c2exp12wk = data->c2exp12wk;
lstData[i].c2exp50wk = data->c2exp50wk;
lstData[i].seasonratio = data->seasonratio;
free(data);
}
}
else
{
statusCode = 404;
responseContent = "<html><body><h1>404 Not Found</h1></body></html>";
headers["Content-Type"] = "text/html; charset=utf-8";
std::string response = "HTTP/1.1 " + std::to_string(statusCode) + (statusCode == 200 ? " OK" : " Not Found") + "\r\n";
for (const auto& header : headers) {
response += header.first + ": " + header.second + "\r\n";
}
response += "\r\n" + responseContent;
return response;
}
statusCode = 200;
responseContent = generateHtmlFromLstData(lstData);
headers["Content-Type"] = "text/html; charset=utf-8";
std::string response = "HTTP/1.1 " + std::to_string(statusCode) + (statusCode == 200 ? " OK" : " Not Found") + "\r\n";
for (const auto& header : headers) {
response += header.first + ": " + header.second + "\r\n";
}
response += "\r\n" + responseContent;
return response;
}
POSTFINAL:
headers["Content-Type"] = "text/html; charset=utf-8";
headers["Access-Control-Allow-Origin"] = "*";
if (method == "OPTIONS") {
headers["Access-Control-Allow-Methods"] = "GET, POST, OPTIONS";
headers["Access-Control-Allow-Headers"] = "Content-Type, Authorization";
responseContent = "";
statusCode = 204;
}
std::string response = "HTTP/1.1 " + std::to_string(statusCode) + (statusCode == 200 ? " OK" : " Not Found") + "\r\n";
for (const auto& header : headers) {
response += header.first + ": " + header.second + "\r\n";
}
response += "\r\n" + responseContent;
return response;
}
void handleClient(SOCKET client_socket, SSL_CTX* ctx) {
static bool isInit = false;
if (!isInit) {
if (!init_thread_mysql_connection("localhost", "admin", "Zls_", "stock", 3306)) {
return;
}
isInit = true;
}
SSL* ssl;
char buffer[1024];
std::string request;
BIO* bio = BIO_new(BIO_s_mem());
ssl = SSL_new(ctx);
SSL_set_fd(ssl, client_socket);
if (SSL_accept(ssl) <= 0) {
ERR_print_errors(bio);
char errBuffer[1024];
std::ostringstream oss;
int len;
while ((len = BIO_read(bio, errBuffer, sizeof(errBuffer))) > 0) {
oss.write(errBuffer, len);
}
BIO_free(bio);
std::ofstream logFile("c:\\sys\\error.log", std::ios::app);
if (logFile.is_open()) {
logFile << "SSL accept failed: " << oss.str() << "\n";
logFile.close();
}
else {
std::cerr << "Failed to open error log file." << std::endl;
}
}
else {
std::cerr << "Failed to create BIO for error logging." << std::endl;
}
while (true) {
int n = SSL_read(ssl, buffer, sizeof(buffer) - 1);
if (n <= 0) {
break;
}
buffer[n] = '\0';
request.append(buffer, n);
std::cout << "Received data: " << request << std::endl;
size_t pos = request.find('\n');
if (pos == std::string::npos) {
continue;
}
std::istringstream req_line(request.substr(0, pos));
std::string method, uri, version;
if (!(req_line >> method >> uri >> version)) {
std::cerr << "Invalid HTTP request line." << std::endl;
break;
}
pos = request.find("\r\n\r\n");
if (pos == std::string::npos) {
continue;
}
std::string body = request.substr(pos + 4);
std::vector<TDXDAT2> lstData;
std::string response = handleRequest2(method, uri, body, lstData);
_CrtDumpMemoryLeaks();
SSL_write(ssl, response.c_str(), response.length());
cleanup_thread_mysql_connection();
if (method != "OPTIONS") {
SSL_shutdown(ssl);
SSL_free(ssl);
closesocket(client_socket);
break;
}
}
}
std::string extractJsonField(const std::string& jsonStr, const std::string& field) {
size_t startPos = jsonStr.find("\"" + field + "\"");
if (startPos == std::string::npos) return "";
startPos = jsonStr.find(":", startPos);
if (startPos == std::string::npos) return "";
startPos++;
bool inQuotes = false;
std::string value;
for (size_t i = startPos; i < jsonStr.length(); ++i) {
char c = jsonStr[i];
if (c == '"') {
if (!inQuotes) inQuotes = true;
else if (i > 0 && jsonStr[i - 1] != '\\') inQuotes = false;
}
if (!inQuotes && (c == ',' || c == '}')) break;
if ((inQuotes || (isdigit(c) || c == '-' || c == '.')) && i >= startPos) {
value += c;
}
}
return value;
}
#define _CRTDBG_MAP_ALLOC
#include <crtdbg.h>
int main()
{
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
bool arbb = FetchDataVec();
if (!arbb)
{
std::cerr << "init vec err." << std::endl;
exit(1);
}
init_openssl(); // 初始化OpenSSL
SSL_CTX* ctx = create_context();
configure_context(ctx);
WSADATA wsdata;
SOCKET s_server, s_accept;
SOCKADDR_IN server_addr;
if (WSAStartup(MAKEWORD(2, 2), &wsdata)) {
std::cerr << "Failed to initialize WinSock." << std::endl;
cleanup_openssl();
return 1;
}
s_server = socket(PF_INET, SOCK_STREAM, 0);
if (s_server == INVALID_SOCKET) {
std::cerr << "Failed to create socket." << std::endl;
WSACleanup();
cleanup_openssl();
return 1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(8226);
if (inet_pton(AF_INET, "127.0.0.1", &(server_addr.sin_addr)) != 1) {
std::cerr << "Failed to convert IP address." << std::endl;
closesocket(s_server);
WSACleanup();
cleanup_openssl();
return 1;
}
if (bind(s_server, (SOCKADDR*)&server_addr, sizeof(SOCKADDR)) == SOCKET_ERROR ||
listen(s_server, 1) == SOCKET_ERROR) {
std::cerr << "Binding or listening failed." << std::endl;
closesocket(s_server);
WSACleanup();
cleanup_openssl();
return 1;
}
while (true) {
sockaddr_in accept_addr;
int len = sizeof(SOCKADDR);
s_accept = accept(s_server, (SOCKADDR*)&accept_addr, &len);
if (s_accept == SOCKET_ERROR) {
std::cerr << "Accept failed." << std::endl;
continue;
}
std::thread client_thread(handleClient, s_accept, ctx);
client_thread.detach();
}
_CrtDumpMemoryLeaks();
closesocket(s_server);
WSACleanup();
SSL_CTX_free(ctx);
cleanup_openssl();
return 0;
}
HTML 控制台输出:
/htmljson:1
POST https://47.120.18.2/htmljson 404 (Not Found)
loadJson @ index-CofVbsKq.js:2
(匿名) @ index-CofVbsKq.js:2
index-CofVbsKq.js:2
弹窗报内存泄露:
corecrt_internal_strtox.h line 1772 expression: _p!=nullptr