diff --git a/CPPCodeRespository/AVLTree.h b/CPPCodeRespository/AVLTree.h new file mode 100644 index 0000000..80e9ef2 --- /dev/null +++ b/CPPCodeRespository/AVLTree.h @@ -0,0 +1,241 @@ +#pragma once +#include +#include + +struct AVLNode { + int value; + int balance; + AVLNode* left; + AVLNode* right; + AVLNode* parent; +}; + +struct AVLTree { + AVLNode* root; +}tree; + +int height(AVLNode* a) { + if (a == 0) { + return 0; + } + int rightheight = height(a->right); + int leftheight = height(a->left); + return rightheight > leftheight ? (rightheight + 1) : (leftheight + 1); +} +struct AVLNode* select(int value, AVLNode* root) { + if (root == 0) { + return 0; + } + if (root->value == value) { + return root; + } + if (root->value > value) { + if (root->left) + return select(value, root->left); + else + return root; + } + if (root->value < value) { + if (root->right) + return select(value, root->right); + else + return root; + } +} +void setBalance(AVLNode* a) { + if (a) + a->balance = height(a->right) - height(a->left); +} + +struct AVLNode* turnLeft(AVLNode* a) { + AVLNode* b = a->right; + if (a->parent != 0) { + if (a->parent->right == a) { + a->parent->right = b; + } + else { + a->parent->left = b; + } + } + b->parent = a->parent; + a->parent = b; + a->right = b->left; + b->left = a; + if (a->right != 0) + a->right->parent = a; + setBalance(a); + setBalance(b); + return b; +} +struct AVLNode* turnRight(AVLNode* a) { + AVLNode* b = a->left; + if (a->parent != 0) { + if (a->parent->right == a) { + a->parent->right = b; + } + else { + a->parent->left = b; + } + } + b->parent = a->parent; + a->parent = b; + a->left = b->right; + if (a->left != 0) + a->left->parent = a; + b->right = a; + setBalance(a); + setBalance(b); + return b; +} + +struct AVLNode* turnLeftThenRight(AVLNode* a) { + a->left = turnLeft(a->left); + return turnRight(a); +} +struct AVLNode* turnRightThenLeft(AVLNode* a) { + a->right = turnRight(a->right); + return turnLeft(a); +} +void rebalance(AVLNode* a) { + setBalance(a); + if (a->balance == -2) { + if (a->left->balance <= 0) { + a = turnRight(a); + } + else { + a = turnLeftThenRight(a); + } + } + else if (a->balance == 2) { + if (a->right->balance >= 0) { + a = turnLeft(a); + } + else { + a = turnRightThenLeft(a); + } + } + if (a->parent) { + rebalance(a->parent); + } + else { + tree.root = a; + } +} + +void insert(int value, AVLNode* root) { + AVLNode* node = select(value, root); + if (node == 0) { + tree.root = (AVLNode*)malloc(sizeof(AVLNode)); + tree.root->value = value; + tree.root->left = tree.root->right = 0; + tree.root->parent = 0; + tree.root->balance = 0; + } + else if (node->value != value) { + if (node->value > value) { + node->left = (AVLNode*)malloc(sizeof(AVLNode)); + node->left->value = value; + node->left->left = node->left->right = 0; + node->left->parent = node; + node->left->balance = 0; + rebalance(node); + } + else if (node->value < value) { + node->right = (AVLNode*)malloc(sizeof(AVLNode)); + node->right->value = value; + node->right->left = node->right->right = 0; + node->right->parent = node; + node->right->balance = 0; + rebalance(node); + } + } +} +void delnodeifhas1childornot(AVLNode* a) { + if (a->parent == 0) { + if (a->left) { + tree.root = a->left; + a->left->parent = 0; + } + else { + tree.root = a->right; + a->right->parent = 0; + } + } + else { + if (a->parent->left == a) { + if (a->left) { + a->parent->left = a->left; + a->left->parent = a->parent; + } + else { + a->parent->left = a->right; + if (a->right) + a->right->parent = a->parent; + } + } + else { + if (a->left) { + a->parent->right = a->left; + a->left->parent = a->parent; + } + else { + a->parent->right = a->right; + if (a->right) + a->right->parent = a->parent; + } + } + rebalance(a->parent); + } +} +struct AVLNode* getmin(AVLNode* a) { + if (a->left) + getmin(a->left); + else + return a; +} +void delnodeifhas2child(AVLNode* a) { + AVLNode* after = getmin(a->right); + a->value = after->value; + delnodeifhas1childornot(after); +} +void del(int value, AVLNode* root) { + AVLNode* node = select(value, root); + if (node->value == value) { + if (node->left && node->right) { + delnodeifhas2child(node); + } + else { + delnodeifhas1childornot(node); + } + } +} +void insertNodetest() { + insert(5, tree.root); + insert(6, tree.root); + insert(7, tree.root); + insert(3, tree.root); + insert(4, tree.root); + insert(4, tree.root); + insert(5, tree.root); + insert(5, tree.root); + insert(3, tree.root); + insert(8, tree.root); + insert(9, tree.root); + insert(10, tree.root); + insert(11, tree.root); + insert(12, tree.root); +} +void delNodetest() { + del(6, tree.root); + del(11, tree.root); + del(12, tree.root); + del(3, tree.root); + del(3, tree.root); + del(5, tree.root); + del(9, tree.root); + del(12, tree.root); +} +int main() { + insertNodetest(); // 测试构建AVL树 + delNodetest(); // 测试删除AVL树节点 +} \ No newline at end of file diff --git a/CPPCodeRespository/Base64Convert.h b/CPPCodeRespository/Base64Convert.h new file mode 100644 index 0000000..f0a31e2 --- /dev/null +++ b/CPPCodeRespository/Base64Convert.h @@ -0,0 +1,196 @@ +#pragma once +//#include "base64.h" +#include +/* + 方法一 +*/ +// Base64 解码 +void Base64Decode(const std::string &input, std::string &output) +{ + //解码表 + const char DecodeTable[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 62, // '+' + 0, 0, 0, + 63, // '/' + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, // '0'-'9' + 0, 0, 0, 0, 0, 0, 0, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, + 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, // 'A'-'Z' + 0, 0, 0, 0, 0, 0, + 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, // 'a'-'z' + }; + + //返回值 + std::string strDecode; + size_t DataByte = input.size(); + const char* Data = input.data(); + int nValue; + size_t i = 0; + while (i < DataByte) + { + if (*Data != '\r' && *Data != '\n') + { + nValue = DecodeTable[*Data++] << 18; + nValue += DecodeTable[*Data++] << 12; + strDecode += (nValue & 0x00FF0000) >> 16; + if (*Data != '=') + { + nValue += DecodeTable[*Data++] << 6; + strDecode += (nValue & 0x0000FF00) >> 8; + if (*Data != '=') + { + nValue += DecodeTable[*Data++]; + strDecode += nValue & 0x000000FF; + } + } + i += 4; + } + else// 回车换行,跳过 + { + Data++; + i++; + } + } + output = strDecode; +} +// Base64 编码 +void Base64Encode(const std::string &input, std::string &output) +{ + //编码表 + const char EncodeTable[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + //返回值 + size_t DataByte = input.size(); + const char* Data = input.data(); + std::string strEncode; + unsigned char Tmp[4] = { 0 }; + int LineLength = 0; + for (int i = 0; i < (int)(DataByte / 3); i++) + { + Tmp[1] = *Data++; + Tmp[2] = *Data++; + Tmp[3] = *Data++; + strEncode += EncodeTable[Tmp[1] >> 2]; + strEncode += EncodeTable[((Tmp[1] << 4) | (Tmp[2] >> 4)) & 0x3F]; + strEncode += EncodeTable[((Tmp[2] << 2) | (Tmp[3] >> 6)) & 0x3F]; + strEncode += EncodeTable[Tmp[3] & 0x3F]; + } + + //对剩余数据进行编码 + int Mod = DataByte % 3; + if (Mod == 1) + { + Tmp[1] = *Data++; + strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2]; + strEncode += EncodeTable[((Tmp[1] & 0x03) << 4)]; + strEncode += "=="; + } + else if (Mod == 2) + { + Tmp[1] = *Data++; + Tmp[2] = *Data++; + strEncode += EncodeTable[(Tmp[1] & 0xFC) >> 2]; + strEncode += EncodeTable[((Tmp[1] & 0x03) << 4) | ((Tmp[2] & 0xF0) >> 4)]; + strEncode += EncodeTable[((Tmp[2] & 0x0F) << 2)]; + strEncode += "="; + } + + output = strEncode; +} +/* + 方法二 +*/ +static const std::string base64_chars = +"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +"abcdefghijklmnopqrstuvwxyz" +"0123456789+/"; + +static inline bool is_base64(unsigned char c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64_encode(unsigned char const* bytes_to_encode, unsigned int in_len) { + std::string ret; + int i = 0; + int j = 0; + unsigned char char_array_3[3]; + unsigned char char_array_4[4]; + + while (in_len--) { + char_array_3[i++] = *(bytes_to_encode++); + if (i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (i = 0; (i <4); i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if (i) + { + for (j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for (j = 0; (j < i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while ((i++ < 3)) + ret += '='; + + } + return ret; + +} +std::string base64_decode(std::string const& encoded_string) { + int in_len = encoded_string.size(); + int i = 0; + int j = 0; + int in_ = 0; + unsigned char char_array_4[4], char_array_3[3]; + std::string ret; + + while (in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; in_++; + if (i == 4) { + for (i = 0; i <4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (i = 0; (i < 3); i++) + ret += char_array_3[i]; + i = 0; + } + } + + if (i) { + for (j = i; j <4; j++) + char_array_4[j] = 0; + + for (j = 0; j <4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for (j = 0; (j < i - 1); j++) ret += char_array_3[j]; + } + + return ret; +} diff --git a/CPPCodeRespository/CPPCodeRespository.cpp b/CPPCodeRespository/CPPCodeRespository.cpp index c11924b..447651b 100644 --- a/CPPCodeRespository/CPPCodeRespository.cpp +++ b/CPPCodeRespository/CPPCodeRespository.cpp @@ -1,36 +1,57 @@ -锘// MongooseServer.cpp: 瀹氫箟鎺у埗鍙板簲鐢ㄧ▼搴忕殑鍏ュ彛鐐广 -// -#include "stdafx.h" -#include "HttpServer.h" -#include "JsonSerializable.h" -#include "HttpServerMultiThread.h" -#include "HttpClient.h" -#include -using namespace std; -void print(string out) +锘#include "stdafx.h" +#include +#include "UnitTest.h" +#include "DumpFile.h" +//class Singleton { +//private: +// Singleton(); +// Singleton(const Singleton&); +// Singleton& operator=(const Singleton&); +//public: +// static Singleton& getInstance(); +//}; +//Singleton& Singleton::getInstance() +//{ +// static Singleton instance; +// return instance; +//} +class Singleton { +private: + Singleton(); + Singleton(const Singleton&); + Singleton& operator=(const Singleton&); +public: + static Singleton& getInstance() + { + static Singleton instance; + return instance; + } +}; +unsigned int __stdcall threadDemo(LPVOID) // void * { - cout << out << endl; + Singleton::getInstance(); + return 0; } +#include +std::mutex mut; int main() { - HttpServer* httpsServer = new HttpServer(); - //////HttpsTest - httpsServer->init("8888"); - httpsServer->startHttpService(); - - ////HttpTest - //httpsServer->init("8442"); - //httpsServer->startHttpService(); - //delete httpsServer; - - ////HttpClient - //HttpClient *client = new HttpClient(); - //client->SendReq("127.0.0.1:8888", print); - //delete client; + mut.lock(); - //澶氱嚎绋嬫祴璇 - //MultiThreadStart(); - system("pause"); + mut.unlock(); + cir + for (int i = 0; i < 10; i++) + { + HANDLE handle = (HANDLE)_beginthreadex(nullptr, 0, threadDemo, nullptr, 0, nullptr); + if (handle != 0) + { + ::WaitForSingleObject(handle, INFINITE); + } + } + //SetUnhandledExceptionFilter(UnhandledExceptionProc); + /*LogInfo("Main test"); + IOCPTest(); + system("pause");*/ return 0; } diff --git a/CPPCodeRespository/CPPEleven.h b/CPPCodeRespository/CPPEleven.h new file mode 100644 index 0000000..7aa2919 --- /dev/null +++ b/CPPCodeRespository/CPPEleven.h @@ -0,0 +1,62 @@ +#pragma once +#include +#include +using namespace std; +function funAddnum; +int addnum(int n1, int n2) +{ + return n1 + n2; +} + +function sumnum = [](int n1, int n2)->int {return n1 - n2; }; + +class Singleton +{ +private: + Singleton() {}; + Singleton(const Singleton&) {}; + Singleton& operator=(const Singleton&) {} +public: + static Singleton& getInstance() + { + static Singleton instance; + return instance; + } +}; +unsigned int __stdcall threadDemo(LPVOID) // void * +{ + Singleton::getInstance(); + return 0; +} +class Product1 { +public: + virtual void process() = 0; +}; +class ProductA1 :public Product1 { + void process() { cout << "drvProductA pro" << endl; } +}; +class ProductB1 :public Product1 { + void process() { cout << "drvProductA1 pro" << endl; } +}; +class Product2 { +public: + virtual void process() = 0; +}; +class ProductA2 :public Product2 { + void process() { cout << "DrvProductB pro" << endl; } +}; +class ProductB2 :public Product2 { + void process() { cout << "DrvProductB1 pro" << endl; } +}; +class Factory { + virtual Product1* Create1() = 0; + virtual Product2* Create2() = 0; +}; +class FactoryA :public Factory { + Product1* Create1() { return new ProductA1; } + Product2* Create2() { return new ProductA2; } +}; +class FactoryB :public Factory { + Product1* Create1() { return new ProductB1; } + Product2* Create2() { return new ProductB2; } +}; diff --git a/CPPCodeRespository/CPPSingleton.h b/CPPCodeRespository/CPPSingleton.h new file mode 100644 index 0000000..134d8f6 --- /dev/null +++ b/CPPCodeRespository/CPPSingleton.h @@ -0,0 +1,61 @@ +#pragma once +class Singleton +{ +public: + static Singleton& instance() + { + static Singleton instance; + return instance; + } +private: + Singleton() {} + ~Singleton() {} + Singleton &operator=(const Singleton& singleton) {} + Singleton(const Singleton&) {} +}; +#include//call_once 在mutex头文件中 +class Singleton +{ +public: + Singleton* instance() + { + static std::once_flag oc;//用于call_once的局部静态变量 + Singleton * m_singinstance; + std::call_once(oc, [&] { m_singinstance = new Singleton(); }); + return m_singinstance; + } +private: + Singleton() {} + ~Singleton() {} + Singleton &operator=(const Singleton& singleton); + Singleton(const Singleton&); +}; +#include +class Singleton +{ +public: + static Singleton* getInstance(); +private: + static std::atomic m_instance; + static std::mutex m_mutex; + Singleton() {} + ~Singleton() {} + Singleton &operator=(const Singleton& singleton); + Singleton(const Singleton&); +}; +std::atomic Singleton::m_instance = nullptr;//静态成员需要先初始化 +std::mutex Singleton::m_mutex; +Singleton* Singleton::getInstance() { + Singleton* tmp = m_instance.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); + if (tmp == nullptr) { + std::lock_guard lock(m_mutex); + tmp = m_instance.load(std::memory_order_relaxed); + if (tmp == nullptr) { + tmp = new Singleton; + std::atomic_thread_fence(std::memory_order_release); + m_instance.store(tmp, std::memory_order_relaxed); + } + } + return tmp; +} diff --git a/CPPCodeRespository/DumpFile.h b/CPPCodeRespository/DumpFile.h new file mode 100644 index 0000000..193ea14 --- /dev/null +++ b/CPPCodeRespository/DumpFile.h @@ -0,0 +1,125 @@ +#pragma once +#include +#include +#include "strsafe.h" +#include "shlwapi.h" +#pragma comment( lib, "Dbghelp.lib" ) +#pragma comment(lib,"shlwapi.lib") +/* 异常处理, Dump文件名 模块名称-年月日-时分秒-进程ID-线程ID */ +LONG WINAPI UnhandledExceptionProc(struct _EXCEPTION_POINTERS *pExceptionPointers) +{ + HMODULE hModule = NULL; + HANDLE hDumpFile; + TCHAR szPath[MAX_PATH] = { 0 }; + TCHAR szNameAppend[128]; + TCHAR szBuild[128] = { 0 }; + TCHAR szError[512] = { 0 }; + SYSTEMTIME stLocalTime; + MINIDUMP_EXCEPTION_INFORMATION ExpParam; + + SetErrorMode(SEM_NOGPFAULTERRORBOX); + + // 日期、时间 + StringCchPrintf(szBuild, 128, _T("Build: %s %s"), __DATE__, __TIME__); + + // 获取异常发生地址所在的模块 + GetModuleHandleEx( + GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, + (LPCTSTR)pExceptionPointers->ExceptionRecord->ExceptionAddress, + &hModule); + + GetModuleFileName(hModule, szPath, MAX_PATH); + + // 构造错误信息 + StringCchPrintf(szError, 512, + _T("Module=%s ,Code=%d ,Flag=%d ,Address=%p"), + szPath, + pExceptionPointers->ExceptionRecord->ExceptionCode, + pExceptionPointers->ExceptionRecord->ExceptionFlags, + pExceptionPointers->ExceptionRecord->ExceptionAddress); + + // 删除之前的DUMP文件,仅保留最近的3个 + if (TRUE) + { + WIN32_FIND_DATA FindFileData; + HANDLE hFind; + int count; + GetModuleFileName(NULL, szPath, MAX_PATH); + StringCchCat(szPath, MAX_PATH, L"*.dmp"); + + // 计数 + hFind = FindFirstFile(szPath, &FindFileData); + + if (hFind != INVALID_HANDLE_VALUE) + { + count = 0; + do + { + count++; + + } while (FindNextFile(hFind, &FindFileData)); + + FindClose(hFind); + + count -= 3; + for (int i = 0; i < count; i++) + { + GetModuleFileName(NULL, szPath, MAX_PATH); + StringCchCat(szPath, MAX_PATH, L"*.dmp"); + hFind = FindFirstFile(szPath, &FindFileData); + if (hFind != INVALID_HANDLE_VALUE) + { + PathRemoveFileSpec(szPath); + StringCchCat(szPath, MAX_PATH, L"\\"); + StringCchCat(szPath, MAX_PATH, FindFileData.cFileName); + DeleteFile(szPath); + FindClose(hFind); + } + } + + } + } + + //构造文件名 + GetLocalTime(&stLocalTime); + + StringCchPrintf(szNameAppend, 128, + _T("%04d%02d%02d-%02d%02d%02d-%ld-%ld.dmp"), + stLocalTime.wYear, stLocalTime.wMonth, stLocalTime.wDay, + stLocalTime.wHour, stLocalTime.wMinute, stLocalTime.wSecond, + GetCurrentProcessId(), GetCurrentThreadId()); + + + GetModuleFileName(NULL, szPath, MAX_PATH); + StringCchCat(szPath, MAX_PATH, szNameAppend); + + //创建文件 + hDumpFile = CreateFile(szPath, GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_WRITE | FILE_SHARE_READ, 0, CREATE_ALWAYS, 0, 0); + + if (hDumpFile != INVALID_HANDLE_VALUE) + { + MINIDUMP_USER_STREAM UserStream[2]; + MINIDUMP_USER_STREAM_INFORMATION UserInfo; + UserInfo.UserStreamCount = 2; + UserInfo.UserStreamArray = UserStream; + UserStream[0].Type = CommentStreamW; + UserStream[0].BufferSize = 128 * sizeof(TCHAR); + UserStream[0].Buffer = szBuild; + UserStream[1].Type = CommentStreamW; + UserStream[1].BufferSize = 512 * sizeof(TCHAR); + UserStream[1].Buffer = szError; + + ExpParam.ThreadId = GetCurrentThreadId(); + ExpParam.ExceptionPointers = pExceptionPointers; + ExpParam.ClientPointers = TRUE; + + MINIDUMP_TYPE MiniDumpWithDataSegs = (MINIDUMP_TYPE)MiniDumpWithFullMemory; + + MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(), + hDumpFile, MiniDumpWithDataSegs, &ExpParam, &UserInfo, NULL); + + CloseHandle(hDumpFile); + } + return EXCEPTION_CONTINUE_SEARCH; +} \ No newline at end of file diff --git a/CPPCodeRespository/HttpClient.cpp b/CPPCodeRespository/HttpClient.cpp index 282b737..ec93cfc 100644 --- a/CPPCodeRespository/HttpClient.cpp +++ b/CPPCodeRespository/HttpClient.cpp @@ -5,7 +5,6 @@ int HttpClient::s_exit_flag = 0; ReqCallback HttpClient::s_req_callback; -auto m_clientlogger = spdlog::daily_logger_mt("HttpClient", "logs/HttpClient.log", 0, 0); // 客户端的网络请求响应 void HttpClient::OnHttpEvent(mg_connection *connection, int event_type, void *event_data) { @@ -18,13 +17,13 @@ void HttpClient::OnHttpEvent(mg_connection *connection, int event_type, void *ev connect_status = *(int *)event_data; if (connect_status != 0) { - m_clientlogger->info("Error connecting to server, error code:{}", connect_status); + LogInfo("Error connecting to server, error code:{}", connect_status); s_exit_flag = 1; } break; case MG_EV_HTTP_REPLY: { - m_clientlogger->info("Got reply:{}{}", (int)hm->body.len, hm->body.p); + LogInfo("Got reply:{}{}", (int)hm->body.len, hm->body.p); std::string rsp = std::string(hm->body.p, hm->body.len); connection->flags |= MG_F_SEND_AND_CLOSE; s_exit_flag = 1; // 每次收到请求后关闭本次连接,重置标记 @@ -36,7 +35,7 @@ void HttpClient::OnHttpEvent(mg_connection *connection, int event_type, void *ev case MG_EV_CLOSE: if (s_exit_flag == 0) { - m_clientlogger->info("Server closed connection"); + LogInfo("Server closed connection"); s_exit_flag = 1; }; break; @@ -46,20 +45,21 @@ void HttpClient::OnHttpEvent(mg_connection *connection, int event_type, void *ev } -// 发送一次请求,并回调处理,然后关闭本次连接 -void HttpClient::SendReq(const std::string &url, ReqCallback req_callback) +// 发送一次请求,并回调处理,然后关闭本次连接,不填写post_data参数的时候默认使用get请求,填写后使用post请求 +void HttpClient::SendReq(const std::string &url, ReqCallback req_callback, const std::string &headers, const std::string &post_data) { + s_exit_flag = 0; // 给回调函数赋值 s_req_callback = req_callback; mg_mgr mgr; mg_mgr_init(&mgr, NULL); - auto connection = mg_connect_http(&mgr, OnHttpEvent, url.c_str(), NULL, NULL); + auto connection = mg_connect_http(&mgr, OnHttpEvent, url.c_str(), headers.c_str(), post_data.c_str()); mg_set_protocol_http_websocket(connection); - m_clientlogger->info("Send http request {}", url.c_str()); + LogInfo("Send http request {}", url.c_str()); while (s_exit_flag == 0) - mg_mgr_poll(&mgr, 500); + mg_mgr_poll(&mgr, 1000); mg_mgr_free(&mgr); } \ No newline at end of file diff --git a/CPPCodeRespository/HttpClient.h b/CPPCodeRespository/HttpClient.h index d21c888..c1f100a 100644 --- a/CPPCodeRespository/HttpClient.h +++ b/CPPCodeRespository/HttpClient.h @@ -17,7 +17,7 @@ class HttpClient HttpClient() {} ~HttpClient() {} - static void SendReq(const std::string &url, ReqCallback req_callback); + static void SendReq(const std::string &url, ReqCallback req_callback,const std::string &headers=nullptr, const std::string &post_data=nullptr); static void OnHttpEvent(mg_connection *connection, int event_type, void *event_data); static int s_exit_flag; static ReqCallback s_req_callback; diff --git a/CPPCodeRespository/HttpInterfaces.cpp b/CPPCodeRespository/HttpInterfaces.cpp index 47fcd54..3cb450c 100644 --- a/CPPCodeRespository/HttpInterfaces.cpp +++ b/CPPCodeRespository/HttpInterfaces.cpp @@ -3,7 +3,7 @@ #include #include "LogWriter.h" #include - +#include "spdlog/fmt/bin_to_hex.h" #ifdef _DEBUG #pragma comment(lib,"Lib\\libeay32MDd.lib") #pragma comment(lib,"Lib\\ssleay32MDd.lib") @@ -11,64 +11,52 @@ #pragma comment(lib,"Lib\\libeay32MD.lib") #pragma comment(lib,"Lib\\ssleay32MD.lib") #endif +using namespace std; static struct mg_mgr m_mgr;//事件管理器 static struct mg_bind_opts m_bind_opts;//用于绑定的属性参数 -static char * m_port = NULL;//端口 - -auto m_loggerInterface = daily_logger_mt("HttpInterfacesForNet", "logs/Http.log", 0, 0); void __stdcall Init() { - m_loggerInterface->flush_on(level::info); - m_loggerInterface->info("Init ..."); + LogInfo("Init ..."); } int __stdcall Bind(mg_event_handler_t callback, const char * port, const char* certName, const char* keyName, char ** errormsg) { if (port == NULL || strcmp(port, "") == 0) { - m_loggerInterface->info("HttpInit:{}", "parameters Invalid"); + LogInfo("HttpInit:{}", "parameters Invalid"); strncpy(*errormsg, "parameters Invalid", strlen("parameters Invalid")); return -1; } mg_mgr_init(&m_mgr, NULL); - m_loggerInterface->info("Bind port:{},cert:{},key:{}", port, certName == NULL ? "" : certName, keyName == NULL ? "" : keyName); + LogInfo("Bind port:{},cert:{},key:{}", port, certName == NULL ? "" : certName, keyName == NULL ? "" : keyName); - int len = strlen(port); - m_port = new char[len + 1]; - strncpy(m_port, port, len + 1); if (certName != NULL && strcmp(certName, "") != 0) { - memset(&m_bind_opts, 0, sizeof(m_bind_opts)); - len = strlen(certName); - m_bind_opts.ssl_cert = new char[len + 1]; - strncpy((char *)m_bind_opts.ssl_cert, certName, len + 1); + m_bind_opts.ssl_cert = certName; } if (keyName != NULL && strcmp(keyName, "") != 0) { - len = strlen(keyName); - m_bind_opts.ssl_key = new char[len + 1]; - strncpy((char *)m_bind_opts.ssl_key, keyName, len + 1); + m_bind_opts.ssl_key = keyName; + } m_bind_opts.error_string = NULL; - //m_loggerInterface->info("Https port:{},cert:{},key:{}", m_port, m_bind_opts.ssl_cert, m_bind_opts.ssl_key); - mg_connection *cn = mg_bind_opt(&m_mgr, m_port, callback, m_bind_opts); + mg_connection *cn = mg_bind_opt(&m_mgr, port, callback, m_bind_opts); if (cn == NULL) { errormsg = (char **)m_bind_opts.error_string; - m_loggerInterface->info("Failed to create listener"); + LogInfo("Failed to create listener"); return -1; } - m_loggerInterface->info("Bind Success"); + LogInfo("Bind Success"); mg_set_protocol_http_websocket(cn); - m_loggerInterface->info("connection Success"); + LogInfo("connection Success"); return 0; } void __stdcall Close() { + LogInfo("Close Serveice..."); mg_mgr_free(&m_mgr); - if (m_port != NULL) - delete m_port; return; } void __stdcall SendErrorResponse(mg_connection *connection, int errCode, const char * errMsg) @@ -77,14 +65,14 @@ void __stdcall SendErrorResponse(mg_connection *connection, int errCode, const c { return; } - m_loggerInterface->info("errCode:{},errMsg:{}", errCode, errMsg); int len = strlen(errMsg); - char* resp = new char[len + 1]; - strncpy(resp, errMsg, len + 1); + char * resp = new char[len + 1]; + strncpy(resp, errMsg, len); resp[len] = '\0'; - mg_send_head(connection, 200, (strlen(resp) + 1), "Access-Control-Allow-Origin: *\r\nContent-Type:text/plain;charset=utf-8\r\nConnection: close");//"Access-Control-Allow-Origin: *" \r\nConnection: close - mg_send(connection, resp, strlen(resp) + 1); + mg_send_head(connection, errCode, strlen(resp), "Access-Control-Allow-Origin: *\r\nContent-Type:text/plain;charset=GBK"); + mg_send(connection, resp, strlen(resp)); + LogInfo("SendData: {},errcode:{}", resp, errCode); delete[] resp; return; } @@ -97,12 +85,12 @@ void __stdcall SendResponse(mg_connection *connection, const char * respMsg) } int len = strlen(respMsg); char * resp = new char[len + 1]; - strncpy(resp, respMsg, len + 1); + strncpy(resp, respMsg, len); resp[len] = '\0'; - mg_send_head(connection, 200, (strlen(resp) + 1), "Access-Control-Allow-Origin: *\r\nContent-Type:text/plain;charset=utf-8");//"Access-Control-Allow-Origin: *" - mg_send(connection, resp, strlen(resp) + 1); - m_loggerInterface->info("SendData: {}", resp); + mg_send_head(connection, 200, strlen(resp), "Access-Control-Allow-Origin: *\r\nContent-Type:text/plain;charset=GBK");//"Access-Control-Allow-Origin: *" + mg_send(connection, resp, strlen(resp)); + LogInfo("SendData: {}", resp); delete[] resp; } //通过调用循环创建一个事件mg_mgr_poll()循环 diff --git a/CPPCodeRespository/HttpServer.cpp b/CPPCodeRespository/HttpServer.cpp index afb738d..3c00e14 100644 --- a/CPPCodeRespository/HttpServer.cpp +++ b/CPPCodeRespository/HttpServer.cpp @@ -13,12 +13,10 @@ namespace spd = spdlog; //静态变量需要在使用前定义 否则lnk2001 std::unordered_map HttpServer::s_handler_map; -auto m_logger = spd::daily_logger_mt("HttpServer", "logs/Http.log", 0, 0); mg_mgr HttpServer::mgr; void HttpServer::init(const std::string port) { m_port = port; - m_logger->flush_on(spd::level::info); } void HttpServer::startHttpService(std::string certName,std::string keyName) { @@ -32,11 +30,11 @@ void HttpServer::startHttpService(std::string certName,std::string keyName) bind_opts.ssl_key = keyName.c_str(); bind_opts.error_string = &err; - m_logger->info("Starting Https server on port:{}, cert:{}, key:{}", m_port.c_str(), bind_opts.ssl_cert, bind_opts.ssl_key); + LogInfo("Starting Https server on port:{}, cert:{}, key:{}", m_port.c_str(), bind_opts.ssl_cert, bind_opts.ssl_key); nc = mg_bind_opt(&mgr, m_port.c_str(), ev_handler, bind_opts); if (nc == NULL) { - m_logger->info("Failed to create listener:{}", err); + LogInfo("Failed to create listener:{}", err); return ; } @@ -60,11 +58,11 @@ void HttpServer::startHttpService() memset(&bind_opts, 0, sizeof(bind_opts)); bind_opts.error_string = &err; - m_logger->info("Starting Http server on port:{}", m_port.c_str()); + LogInfo("Starting Http server on port:{}", m_port.c_str()); nc = mg_bind_opt(&mgr, m_port.c_str(), ev_handler, bind_opts); if (nc == NULL) { - m_logger->info("Failed to create listener:{}", err); + LogInfo("Failed to create listener:{}", err); return ; } @@ -85,59 +83,10 @@ bool HttpServer::route_check(http_message *http_msg,const char *route_prefix) else return false; } -//web server -void HttpServer::HandleHttpEvent(mg_connection *connection, http_message *http_req) -{ - //std::string req_str = std::string(http_req->message.p, http_req->message.len); - //m_logger->info("got request: %s\n", req_str.c_str()); - - //// 先过滤是否已注册的函数回调 - //std::string url = std::string(http_req->uri.p, http_req->uri.len); - //std::string body = std::string(http_req->body.p, http_req->body.len); - //auto it = s_handler_map.find(url); - //if (it != s_handler_map.end()) - //{ - // ReqHandler handle_func = it->second; - // handle_func(url, body, connection, SendData); - //} - - //// 其他请求 - //if (route_check(http_req, "/")) - //{ - // static mg_serve_http_opts s_server_option; - // mg_serve_http(connection, http_req, s_server_option); - //} - //else if (route_check(http_req, "/api/hello")) - //{ - // // 直接回传 - // SendData(connection, "welcome to httpserver"); - //} - //else if (route_check(http_req, "/api/sum")) - //{ - // // 简单post请求,加法运算测试 - // char n1[100], n2[100]; - // double result; - // /* Get form variables */ - // mg_get_http_var(&http_req->body, "n1", n1, sizeof(n1)); - // mg_get_http_var(&http_req->body, "n2", n2, sizeof(n2)); - - // /* Compute the result and send it back as a JSON object */ - // result = strtod(n1, NULL) + strtod(n2, NULL); - // SendData(connection, std::to_string(result)); - //} - //else - //{ - // mg_printf( - // connection, - // "%s", - // "HTTP/1.1 501 Not Implemented\r\n" - // "Content-Length: 0\r\n\r\n"); - //} -} void HttpServer::ev_handler(struct mg_connection *nc, int ev, void *p) { - m_logger->info("ev_handler event:{}", ev); + LogInfo("ev_handler event:{}", ev); switch (ev) { case MG_EV_ACCEPT: @@ -157,13 +106,13 @@ void HttpServer::ev_handler(struct mg_connection *nc, int ev, void *p) //请求方式 get/post std::string strMethod(hm->method.p, (hm->method.p + hm->method.len)); - m_logger->info("Method:{}", strMethod.c_str()); + LogInfo("Method:{}", strMethod.c_str()); //请求体 std::string strbody(hm->body.p, (hm->body.p + hm->body.len)); - m_logger->info("Body:{}", strbody.c_str()); + LogInfo("Body:{}", strbody.c_str()); //请求uri std::string struri(hm->uri.p, (hm->uri.p + hm->uri.len)); - m_logger->info("Uri:{}", struri.c_str()); + LogInfo("Uri:{}", struri.c_str()); if (struri == "close" || struri=="/close") { HttpServer::Close(mgr); @@ -174,7 +123,7 @@ void HttpServer::ev_handler(struct mg_connection *nc, int ev, void *p) { std::string strKey(hm->header_names[i].p, (hm->header_names[i].p + hm->header_names[i].len)); std::string strValue(hm->header_values[i].p, (hm->header_values[i].p + hm->header_values[i].len)); - m_logger->info("Header:{} {}" , strKey.c_str(), strValue.c_str()); + LogInfo("Header:{} {}" , strKey.c_str(), strValue.c_str()); i++; } //std::string struri(hm->header_names, (hm->uri.p + hm->uri.len)); @@ -210,7 +159,7 @@ void HttpServer::SendData(mg_connection * nc, const char* sdata) mg_send_head(nc, 200,strlen(sdata), "Access-Control-Allow-Origin: *"); mg_send(nc, sdata, strlen(sdata)); - m_logger->info("SendData: {}", sdata); + LogInfo("SendData: {}", sdata); } //支持跨域 void HttpServer::SendResponse(mg_connection *connection,const char* rsp) @@ -222,7 +171,7 @@ void HttpServer::SendResponse(mg_connection *connection,const char* rsp) //发送空白字符块,结束当前响应 mg_send_http_chunk(connection, "", 0); connection->flags |= MG_F_SEND_AND_CLOSE; - m_logger->info("SendResponse {}", rsp); + LogInfo("SendResponse {}", rsp); } bool HttpServer::Close(mg_mgr mgr) { diff --git a/CPPCodeRespository/HttpServer.h b/CPPCodeRespository/HttpServer.h index 85e4547..3c7982e 100644 --- a/CPPCodeRespository/HttpServer.h +++ b/CPPCodeRespository/HttpServer.h @@ -34,7 +34,6 @@ class HttpServer void RemoveHandler(const std::string &url); //路径判断 uri解析 static bool route_check(http_message *http_msg, const char *route_prefix); - static void HandleHttpEvent(mg_connection *connection, http_message *http_req); static void ev_handler(struct mg_connection *nc, int ev, void *p); //发送数据 static void SendData(mg_connection * nc,const char* sdata); diff --git a/CPPCodeRespository/HttpWinInet.h b/CPPCodeRespository/HttpWinInet.h new file mode 100644 index 0000000..f875fe5 --- /dev/null +++ b/CPPCodeRespository/HttpWinInet.h @@ -0,0 +1,348 @@ +#pragma once +#include +#include +#include +#include"tchar.h" +#pragma comment(lib, "Wininet.lib") + +enum DOWNLOADSTATE { DOWNLOAD_SUCCESS, DOWNLOAD_EMPTY, DOWNLOAD_ERROR, DOWNLOAD_TIMEOUT }; +typedef std::function< VOID(ULONGLONG ullTotalSize, ULONGLONG ullCurrentSize, float fPercent) > FHttpDownNotify; +class CHttpDownLoad +{ +public: + CHttpDownLoad() {}; + DOWNLOADSTATE DownLoad(LPCTSTR szURL, LPCTSTR szFilePath, DWORD dwTimeOut, FHttpDownNotify fNotfiy) + { + for (int i = 0; i<3; i++) + { + OutputDebugString(L"DownLoad ......................."); + if (DOWNLOAD_SUCCESS == _Download(szURL, szFilePath, dwTimeOut, fNotfiy)) + { + return DOWNLOAD_SUCCESS; + } + } + OutputDebugString(L"DownLoad .......................Error............"); + return DOWNLOAD_ERROR; + //return _Download( szURL, szFilePath, dwTimeOut, fNotfiy); + } + +private: + struct THREAD_PARAM + { + TCHAR szURL[1024]; + TCHAR szPath[1024]; + HINTERNET hSession; + HINTERNET hRequest; + HINTERNET hConnect; + BOOL bRet; + }; +private: + DOWNLOADSTATE _Download(LPCTSTR szURL, LPCTSTR szFilePath, DWORD dwTimeOut, FHttpDownNotify fNotfiy) + { + if (NULL == szURL) + { + return DOWNLOAD_ERROR; + } + + // 必须清除IE缓存 + DeleteUrlCacheEntry(szURL); + + HINTERNET hSession = InternetOpen(L"", + INTERNET_OPEN_TYPE_PRECONFIG, + NULL, + NULL, + 0); + if (NULL == hSession) + { + OutputDebugString(L"StartDownload 创建Session失败\n"); + return DOWNLOAD_ERROR; + } + + THREAD_PARAM threadParm; + ZeroMemory(&threadParm, sizeof(THREAD_PARAM)); + _tcscpy_s(threadParm.szURL, 1024 - 1, szURL); + if (szFilePath != NULL) + { + _tcscpy_s(threadParm.szPath, 1024 - 1, szFilePath); + } + threadParm.hSession = hSession; + + HANDLE hThread = CreateThread( + NULL, // Pointer to thread security attributes + 0, // Initial thread stack size, in bytes + WorkerFunction, // Pointer to thread function + &threadParm, // The argument for the new thread + 0, // Creation flags + NULL // Pointer to returned thread identifier + ); + + // Wait for the call to InternetConnect in worker function to complete + if (WaitForSingleObject(hThread, dwTimeOut) == WAIT_TIMEOUT) + { + OutputDebugString(L"StartDownload 与服务器通讯超时\n"); + InternetCloseHandle(hSession); + WaitForSingleObject(hThread, INFINITE); + CloseHandle(hThread); + if (NULL != threadParm.hConnect) + { + InternetCloseHandle(threadParm.hConnect); + } + if (NULL != threadParm.hRequest) + { + InternetCloseHandle(threadParm.hRequest); + } + return DOWNLOAD_TIMEOUT; + } + CloseHandle(hThread); + + if (!threadParm.bRet) + { + OutputDebugString(L"StartDownload 与服务器通讯失败\n"); + InternetCloseHandle(hSession); + if (NULL != threadParm.hConnect) + { + InternetCloseHandle(threadParm.hConnect); + } + if (NULL != threadParm.hRequest) + { + InternetCloseHandle(threadParm.hRequest); + } + return DOWNLOAD_ERROR; + } + + DWORD dwStatusCode = 0; + DWORD dwBufLen = sizeof(dwStatusCode); + if (!HttpQueryInfo(threadParm.hRequest, HTTP_QUERY_STATUS_CODE | HTTP_QUERY_FLAG_NUMBER, (LPVOID)&dwStatusCode, &dwBufLen, NULL)) + { + OutputDebugString(L"StartDownload 查询状态代码失败\n"); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_ERROR; + } + if (dwStatusCode != 200) + { + OutputDebugString(L"StartDownload 状态代码非OK\n"); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_ERROR; + } + + if (!szFilePath) + { + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_SUCCESS; + } + + // 接收服务器返回 + DWORD dwBytesToRead = 0; + dwBufLen = sizeof(dwBytesToRead); + if (!HttpQueryInfo(threadParm.hRequest, + HTTP_QUERY_CONTENT_LENGTH | HTTP_QUERY_FLAG_NUMBER, + (LPVOID)&dwBytesToRead, + &dwBufLen, + NULL)) + { + OutputDebugString(L"StartDownload 查询文件大小失败\n"); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_ERROR; + } + + if (0 == dwBytesToRead) + { + OutputDebugString(L"StartDownload 查询文件大小失败\n"); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_EMPTY; + } + + HANDLE hFile = CreateFile(szFilePath, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (INVALID_HANDLE_VALUE == hFile) + { + OutputDebugString(L"StartDownload 创建文件失败\n"); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_ERROR; + } + + DWORD dwRead = 0; + DWORD dwWrite = 0; + DWORD dwTotal = 0; + + if (fNotfiy) + { + char szRecvBuf[1024] = { 0 }; + while (InternetReadFile(threadParm.hRequest, szRecvBuf, 1024, &dwRead)) + { + if (0 == dwRead) + { + OutputDebugString(L"InternetReadFile 0 ==dwRead break"); + break; + } + + BOOL bRet = WriteFile(hFile, szRecvBuf, dwRead, &dwWrite, NULL); + if (!bRet || dwRead != dwWrite) + { + OutputDebugString(L"InternetReadFile dwRead != dwWrite"); + break; + } + dwTotal = dwTotal + dwWrite; + + // 返回下载进度。。。 + if (NULL != fNotfiy) + { + float f = (float)dwTotal / dwBytesToRead; + fNotfiy(dwBytesToRead, dwTotal, f); + } + } + + if (dwTotal != dwBytesToRead) + { + OutputDebugString(L"StartDownload 接收数据失败\n"); + CloseHandle(hFile); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + DeleteFile(szFilePath); + return DOWNLOAD_ERROR; + } + } + else + { + char *szRecvBuf = new char[dwBytesToRead]; + ZeroMemory(szRecvBuf, dwBytesToRead); + BOOL bRet = InternetReadFile(threadParm.hRequest, szRecvBuf, dwBytesToRead, &dwRead); + if (bRet) + { + bRet = WriteFile(hFile, szRecvBuf, dwRead, &dwWrite, NULL); + if (!bRet) + { + OutputDebugString(L"StartDownload 写入数据失败\n"); + CloseHandle(hFile); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + DeleteFile(szFilePath); + delete[] szRecvBuf; + return DOWNLOAD_ERROR; + } + } + delete[] szRecvBuf; + } + CloseHandle(hFile); + InternetCloseHandle(hSession); + InternetCloseHandle(threadParm.hConnect); + InternetCloseHandle(threadParm.hRequest); + return DOWNLOAD_SUCCESS; + } + + +private: + static DWORD WINAPI WorkerFunction(LPVOID lpParam) + { + THREAD_PARAM* worker = (THREAD_PARAM*)lpParam; + + URL_COMPONENTS uc; + TCHAR szScheme[1024] = { 0 }; + TCHAR szHostName[1024] = { 0 }; + TCHAR szUserName[1024] = { 0 }; + TCHAR szPassword[1024] = { 0 }; + TCHAR szUrlPath[1024] = { 0 }; + TCHAR szExtraInfo[1024] = { 0 }; + + uc.dwStructSize = sizeof(uc); + uc.lpszScheme = szScheme; + uc.lpszHostName = szHostName; + uc.lpszUserName = szUserName; + uc.lpszPassword = szPassword; + uc.lpszUrlPath = szUrlPath; + uc.lpszExtraInfo = szExtraInfo; + + uc.dwSchemeLength = 1024; + uc.dwHostNameLength = 1024; + uc.dwUserNameLength = 1024; + uc.dwPasswordLength = 1024; + uc.dwUrlPathLength = 1024; + uc.dwExtraInfoLength = 1024; + BOOL bRet = InternetCrackUrl(worker->szURL, 0, 0, &uc); + if (!bRet) + { + worker->bRet = FALSE; + worker->hConnect = NULL; + worker->hRequest = NULL; + + OutputDebugString(L"InternetCrackUrl失败\n"); + return 0; + } + + HINTERNET hConnect = InternetConnect(worker->hSession, + uc.lpszHostName, + uc.nPort, + NULL, + NULL, + INTERNET_SERVICE_HTTP, + 0, + 0); + if (NULL == hConnect) + { + worker->bRet = FALSE; + worker->hConnect = NULL; + worker->hRequest = NULL; + OutputDebugString(L"InternetConnect失败\n"); + return 0; + } + else + { + worker->hConnect = hConnect; + } + + + TCHAR szUrl[1024] = { 0 }; + _tcscat_s(szUrl, _countof(szUrl), uc.lpszUrlPath); + _tcscat_s(szUrl, _countof(szUrl), uc.lpszExtraInfo); + + CONST TCHAR *szAcceptType[2] = { _T("Accept: */*"),NULL }; + HINTERNET hRequest = HttpOpenRequest(hConnect, + L"GET", + szUrl, + L"HTTP/1.1", + NULL, + (const TCHAR **)&szAcceptType, + 0, + 0); + if (NULL == hRequest) + { + worker->hRequest = NULL; + worker->bRet = FALSE; + OutputDebugString(L"HttpOpenRequest失败\n"); + return 0; + } + else + { + worker->hRequest = hRequest; + } + + if (!HttpSendRequest(hRequest, NULL, 0, NULL, 0)) + { + worker->bRet = FALSE; + OutputDebugString(L"HttpSendRequest失败\n"); + return 0; + } + worker->bRet = TRUE; + return 0; + } + +}; \ No newline at end of file diff --git a/CPPCodeRespository/Lib/CA-key.pem b/CPPCodeRespository/Lib/CA-key.pem new file mode 100644 index 0000000..3dc32ee --- /dev/null +++ b/CPPCodeRespository/Lib/CA-key.pem @@ -0,0 +1,40 @@ +-----BEGIN PRIVATE KEY----- +MIIG/gIBADANBgkqhkiG9w0BAQEFAASCBugwggbkAgEAAoIBgQDLeW/q6huTa+ng +0uQgzkeekdsWhf74cL5KnhDIYIJI8uTtobD2384loL6AWIGdXaNLa6h3heDkCaRQ +nhTbelfUxFiTzeSVev6+JmARi+KLTamiG8G0PU58UNMJc6oZzDTYuWPH1OlDlX3B +OIK/2YRMndhIwuIXJOpvokz1fBko4JJVJ6hWmF0Bw9VYM0FdfPGAz5yPUhof48kV +Ub3+s6w2Cbu/Rrzw6Dx1+RDzKLNIm3oi3QMH7JLMCSGRAs4N+2NLVfqsHKHrXgpq +ARQlt2e3dOb1I1qCt6B5FSjVdNuRR0NL/R2ral9dL31rk6YkhLaON0mq046jryFU +v4awSjhhWX/OIzCmBPbSsqHrRpfrWyyspEyFPWQ71hXbr9Gn0fWMgnXGlZeEHptL +mYW6MnJ8UhjB7gGFeWDOSUpN4ZAvd7GglT1wwadYU+9ca0Ky14xshShB5yzXDEp4 +Ea/490sJXnSNfW7c5o+FUEuvD0D3/xxH9geWkwTXuuIMFmOjwYMCAwEAAQKCAYEA +qBb9+dbESRkQ8IXHp8JBMCHWF9lCNQMOcJ37x0zS1Giz7gtxIcDpj/Qm6+gxy0qb +p6acWYDjs/6zG1Y8bMO44zAA7LleaI5e+77ABj7FO8dAp4a+kqNCvzgV3u0KTJ2B +2rfsUhz1RrusU37XpJ2QyapsDk/QbsY0VVyCrxmBv18mA+rrCf58dwTMrjxJd23M +JFleQJfWtRl7+Hy6tDrBvTJ1QyKw22M+70Z+ViH9WbH3R+3Enzs0WhIBBMaIasyM +VVt0FoWbT6bx33g3MvJOXj/f/RjbA/vUuKWibMTl94BexBzz0fmhhK8D8bfvp6oL +awjmSuykgQhtglqGpNaxdsKkZuQxaDpJY2czagdV2s4W2Utj7/h2nQRQBIUGpu7/ +SCKO+kdeF0ZpeJjdjuwzwvd0a3sGakvmYrhBvmSu68S48sjVSJQVO2ygwGxNHedT +zJIRLKxEoh+t+doMn8lDSuvIGqGOPvJbwBb1G2H6YkVeI80D8g35IrsGqlYcfdXh +AoHBAOuxFv1qP52oTedej6094HJnLSB5DY6PX1TPBk2UPT54T4sLGIAx3+xFH13e +m5WEN4AU5IP5OeKVrehrQDLeQx3xxCfbXwU0wdnzQ25eETOOYAZSRHCMv4qx/NN6 +OIJ9N4WaR8gYOYLUuigZYVfCNVkVyTPtLfPUuaD8T0tl4AVl+MxYXijAd7In0DwF +2p4apZvsixBjAvPsC2/qaDfETuE4+QbrbagqQ+1goak2AFJ3rJkXdl/B2/IJ7EnI +zqvovQKBwQDdAbF040loKOo7lZFWBnzYdUm5KQ+rLIG7Ab8bmS/AMgzoLJjQ5ltm +K3wuEcnkzm974+9gJe7ICVL91Xi/SueQEBb/Hc9DDvSoBSXt8Z/YLk/SGHh9Q2Jf +a0QYW1+NmIAbXPVcodTd122A7J9JyQbqU8ktIPPF6Qrlz/69+/53QjbCo7AfRsfj +v08WWQxp57vOFzcyUp8y8PX/eMmgwLr1q2XR6mKl7rnZoV+uF6QmzpHRM8G7lW7z +eo6Tu7kmlz8CgcEA2eH/N8wF/VA+nHpNZkECgaAiFpfx0W13Gqa70/ILX/nGxuo9 +/xycPgZ0hcmpmOH+kLg/vEUknvPyLh8f3Sadc0wyIwpoYB6yajK5jokFa9zdplpd +DJMA6025RSMCpJbvQeIrI65JVEolwbYcyA0wVieOtiM3zOZFqK42+6O1IihvhTDX +8uJihN7LYQGkZW6K1Icq075EV4xJ0m8nYw5mQUzy4dO4rrJL02D2ccALMjGR7IDF +HKbRFoLX3in17PQdAoHAArbznBDypOHjxqmWqGzZ+bqvFiQn+h1I1qg11bvy9zRm +Li/mDKLXupCMLPCw/yt9+RKarR6qKTDcIRwPKKJd58oazjVqh1NWs/2kMqEGKpyf +BGCikj9SpQNnSblNmiqmYC+rH+EpATSVNsExT7G1cQlobjJ6bBLpvFrqsSC4RnS8 +wXVLQ4cWC3kdGpQrb92V0/k7B1Y2eGS3UNUF/QCBC2V4kbSEU69z/vVZfITz0jo1 +VlGBbrFuNHVr7OqgYpX3AoHAXQS+T2QQsQzIhsegK8bf2zBRL8ahQAcY9vv2XkvI +L2MD8jAyA/nP3JMXxqgnkP8dBmIZKXsUtQvSUdnr5z9Or7wXipSzrYVgCYkUEVvQ +oulSYJpsLNVrzWlMH2MefMdLCY0BgkXNn6PjydE86NxzJISyHUZaVVRuFF69oaqO +eftVjpsV6Pm1gGyu/I1QKJx8Gt28YP95kKvyl5zMdZAOBuYLRbeqACRhHS+O9jvK +abv+8k6jFFHguyWB2f0i8MBb +-----END PRIVATE KEY----- diff --git a/CPPCodeRespository/Lib/CA.pem b/CPPCodeRespository/Lib/CA.pem new file mode 100644 index 0000000..47691e6 --- /dev/null +++ b/CPPCodeRespository/Lib/CA.pem @@ -0,0 +1,30 @@ +-----BEGIN CERTIFICATE----- +MIIFDzCCA3egAwIBAgIQbv98RsdQER7Q4HWy7cwElzANBgkqhkiG9w0BAQsFADCB +nzEeMBwGA1UEChMVbWtjZXJ0IGRldmVsb3BtZW50IENBMTowOAYDVQQLDDFERVNL +VE9QLTFSUEdHNUdcemhhbmdAREVTS1RPUC0xUlBHRzVHICgxMyBjb2RpbmcpMUEw +PwYDVQQDDDhta2NlcnQgREVTS1RPUC0xUlBHRzVHXHpoYW5nQERFU0tUT1AtMVJQ +R0c1RyAoMTMgY29kaW5nKTAeFw0xOTEyMzExMjQ4MzBaFw0yOTEyMzExMjQ4MzBa +MIGfMR4wHAYDVQQKExVta2NlcnQgZGV2ZWxvcG1lbnQgQ0ExOjA4BgNVBAsMMURF +U0tUT1AtMVJQR0c1R1x6aGFuZ0BERVNLVE9QLTFSUEdHNUcgKDEzIGNvZGluZykx +QTA/BgNVBAMMOG1rY2VydCBERVNLVE9QLTFSUEdHNUdcemhhbmdAREVTS1RPUC0x +UlBHRzVHICgxMyBjb2RpbmcpMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKC +AYEAy3lv6uobk2vp4NLkIM5HnpHbFoX++HC+Sp4QyGCCSPLk7aGw9t/OJaC+gFiB +nV2jS2uod4Xg5AmkUJ4U23pX1MRYk83klXr+viZgEYvii02pohvBtD1OfFDTCXOq +Gcw02Lljx9TpQ5V9wTiCv9mETJ3YSMLiFyTqb6JM9XwZKOCSVSeoVphdAcPVWDNB +XXzxgM+cj1IaH+PJFVG9/rOsNgm7v0a88Og8dfkQ8yizSJt6It0DB+ySzAkhkQLO +DftjS1X6rByh614KagEUJbdnt3Tm9SNagregeRUo1XTbkUdDS/0dq2pfXS99a5Om +JIS2jjdJqtOOo68hVL+GsEo4YVl/ziMwpgT20rKh60aX61ssrKRMhT1kO9YV26/R +p9H1jIJ1xpWXhB6bS5mFujJyfFIYwe4BhXlgzklKTeGQL3exoJU9cMGnWFPvXGtC +steMbIUoQecs1wxKeBGv+PdLCV50jX1u3OaPhVBLrw9A9/8cR/YHlpME17riDBZj +o8GDAgMBAAGjRTBDMA4GA1UdDwEB/wQEAwICBDASBgNVHRMBAf8ECDAGAQH/AgEA +MB0GA1UdDgQWBBQEHqlQI18TOO9MT8btRCI6dhAUijANBgkqhkiG9w0BAQsFAAOC +AYEAU5dYnzlYj+LtmxRGGpZvSxTJgx01XwXfNnJPJzs5uS48rh3OMx8dNsVa4ndm +JjL/yHufKEe3PpYZL9Y8S5AikrTh6LKIfuxrTzKWLC07XVvsqJUaJzXi4cCb5dfz +JOgGqrSp44dfwhJirIkmfIxeIIycthdfwez44G3X52UYmoLJBEOX1VoVpetIsC5g +jz0CqnD2lHmhPM1WjZCu6MCt7x1Ang7xBgYdLIUzyIW6DKsYJOwjE8CEPxvbPJFS +GZ0/j77kzIbiNvo3LVSvkPFM5qc/cUDqMpjIjLRMgwiTf8+O8446+lFDVfFu06yB +DvKfYXKl1Ca93OMOOS8EOs+0M/MNnMeUvMoje9s2h35q3UNtoo9pfdr6xR0+BVw5 +Ek/8Nr7rjtbBK4QdoCY7OE6REYD6YR1B6MzwXrqpoequsalp2/4Vkv69WzlkyLr5 +sP6yJYpp3+uZ5j6PMjgAeBIGSU4KRmO4tIpn5veh4m4x3CH4fY7uMPRHI0nZXOCJ +sCvj +-----END CERTIFICATE----- diff --git a/CPPCodeRespository/Lib/libeay32MD.dll b/CPPCodeRespository/Lib/libeay32MD.dll new file mode 100644 index 0000000..b1641cd Binary files /dev/null and b/CPPCodeRespository/Lib/libeay32MD.dll differ diff --git a/CPPCodeRespository/Lib/libeay32MDd.dll b/CPPCodeRespository/Lib/libeay32MDd.dll new file mode 100644 index 0000000..9da9dd1 Binary files /dev/null and b/CPPCodeRespository/Lib/libeay32MDd.dll differ diff --git a/CPPCodeRespository/Lib/mkcert.exe b/CPPCodeRespository/Lib/mkcert.exe new file mode 100644 index 0000000..e3dbc9f Binary files /dev/null and b/CPPCodeRespository/Lib/mkcert.exe differ diff --git a/CPPCodeRespository/Lib/server.key b/CPPCodeRespository/Lib/server.key new file mode 100644 index 0000000..e229be9 --- /dev/null +++ b/CPPCodeRespository/Lib/server.key @@ -0,0 +1,28 @@ +-----BEGIN PRIVATE KEY----- +MIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQDjjLx6MLr+qE9Q +LqJz88C0udOZgFtrPg+8TYmIc+naOVBeVQwW1yG+xGGuN/kNTa2y8buyW5I+9vR7 +GlV8h5Fi6aFXRjXvdwGQDFr0fcwQTbgyu9347Cs/BUjzZ0nEA/P0Mi4xLyeJwapF +Bxdg+5a2lb8VxVaidqTsa0nlXvxjjiHHHS3SeMJELEQHSWWPXu9BFEvhkR5F9HTQ +PPZXFGFMQ5OgA9nu4lfmk8dTUthKIybolBKngIiIi2xk81TEwqmk/sm/FBHkLBVK +0EaCWYcJTDfxhnxWZL0inTBXn6JrscsPUOvxHiNr8Pzj3MxbDrwoELBhbnaDdOdr +JQdoyL+hAgMBAAECggEAchNA/eTmKfqI4IKwkH63siKi0QaHTikrzFP2ygCKUQuA +nfn2+JBba36aFbQb2C6EEPydA1pi48v8XqaiCq8QFM1ZRB5/tZAsqWF4S6+xGM9N +s6l5K2yCdbKZkuTKF0mACIELpT6ljKsZSEe40bbvJJPH2ws2VnYyUg+rWSEYWHOb +Vbe8tFbM6MQuKiEwWx/ET0lydm9/1tCAH61addG6h6T2otNYFWl5uLKSaDGyYZCA +zQs9UXyBCuG3fV3kY4ZRG+AS7zH8njiY7VC+8YR8pRS44rYHsl2xSDIOCOOre1N1 +cMp6ekTcUy88fw/68IWh3ZrytodTbed7ydKW+3g9HQKBgQD/ygRDbYUxEan5Ue6d +KThVHB5CsJnSqpcpIpYSKBGgUSN38qFsyTme7eM5dTsFfCpUuvIOGtOJ6TXTDBC0 +IM5W6s8Ow/en9wtLQQqXNw8fyLFCYyORszPHzPypYneZPlElXK4Tvp2bFLmiKJCY +SxBcAQYwYkRt32B7zw6ZaV+WjwKBgQDjvMKASOucG/VwlP4ScTLY9CmwlW0W/n88 +u3SOHykmL5d1/mtjPOHR5WcTmaogNtXHQ/TDlWFu7DvQIXuFNcPOb7f6wTnqP35g +Ie3rbeQGgzjyPcXgjz+7/tLaSqCIiNKctD/o56a7MJCAxtdnchCTAgAMdryvDIOc +piTWmDLezwKBgQDowPfeL2N6ghtMLpzVT7Pd5mc2wiJGy0ofeURbozBe1FZVCGiR +aA3Rq6APIbiiRhjy3uXxpcGGBbsfnyP39L4t4x6kzfemVKtnP/kWHljZ0DJUOYgd +RZbBoarrqxkvTcBjIhGZD+O0QUil4QmqOuvY/GmYT2L7I79VCdW8DWGYywKBgQCx +jkG28yN/Gu1JUWCl0EvsirDWVCoxe0qIdz5wcCsM8p4MCMiBHr6Rf2HWDkBtzVLv +gTQcKSNF8DjSFMjRGxIGqWOvxWb6E3bcTJfKrmrSCQ0lELRuWEFAuXR7bSOsT8Cl +HIOXesSrvTlsrZrTtELn2u9eyFRjxkX2pDKkfRVsUQKBgFBMg4P9mGbnSjqMjttH +kmON+9RKJU507BxiAu3s6YL/H1RnpA3hF0+CAnQ9k0ENVK7XTLx/V8e4CYrgSpv6 +RhBFAAP7pXXzW97rvlZRkmh7BKo5C/tLoOkXGpK5O0EKm1417HN33sR1ixqOb7pu +RqmsmjFa9eh39IYC4oZ1kxEl +-----END PRIVATE KEY----- diff --git a/CPPCodeRespository/Lib/server.pem b/CPPCodeRespository/Lib/server.pem new file mode 100644 index 0000000..c63d843 --- /dev/null +++ b/CPPCodeRespository/Lib/server.pem @@ -0,0 +1,26 @@ +-----BEGIN CERTIFICATE----- +MIIEdzCCAt+gAwIBAgIRAOUNQBDbpbxg0kKxyq8VQsgwDQYJKoZIhvcNAQELBQAw +gZ8xHjAcBgNVBAoTFW1rY2VydCBkZXZlbG9wbWVudCBDQTE6MDgGA1UECwwxREVT +S1RPUC0xUlBHRzVHXHpoYW5nQERFU0tUT1AtMVJQR0c1RyAoMTMgY29kaW5nKTFB +MD8GA1UEAww4bWtjZXJ0IERFU0tUT1AtMVJQR0c1R1x6aGFuZ0BERVNLVE9QLTFS +UEdHNUcgKDEzIGNvZGluZykwHhcNMTkwNjAxMDAwMDAwWhcNMjkxMjMxMTI0OTQ2 +WjBlMScwJQYDVQQKEx5ta2NlcnQgZGV2ZWxvcG1lbnQgY2VydGlmaWNhdGUxOjA4 +BgNVBAsMMURFU0tUT1AtMVJQR0c1R1x6aGFuZ0BERVNLVE9QLTFSUEdHNUcgKDEz +IGNvZGluZykwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDjjLx6MLr+ +qE9QLqJz88C0udOZgFtrPg+8TYmIc+naOVBeVQwW1yG+xGGuN/kNTa2y8buyW5I+ +9vR7GlV8h5Fi6aFXRjXvdwGQDFr0fcwQTbgyu9347Cs/BUjzZ0nEA/P0Mi4xLyeJ +wapFBxdg+5a2lb8VxVaidqTsa0nlXvxjjiHHHS3SeMJELEQHSWWPXu9BFEvhkR5F +9HTQPPZXFGFMQ5OgA9nu4lfmk8dTUthKIybolBKngIiIi2xk81TEwqmk/sm/FBHk +LBVK0EaCWYcJTDfxhnxWZL0inTBXn6JrscsPUOvxHiNr8Pzj3MxbDrwoELBhbnaD +dOdrJQdoyL+hAgMBAAGjZzBlMA4GA1UdDwEB/wQEAwIFoDATBgNVHSUEDDAKBggr +BgEFBQcDATAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFAQeqVAjXxM470xPxu1E +Ijp2EBSKMA8GA1UdEQQIMAaHBH8AAAEwDQYJKoZIhvcNAQELBQADggGBALD6Qslv +7GC4SsJdk1d1NiCjxcacZtUFSOAwoPblWCF+SEyl0x9qx4xW5715T0OErwY+ozds +4gtgx1KnaE3BnwIxW9car8PhFMNEHuWy64QvoU0PIBUDLgg+ynTCgfku+ZJuVPHO +ArM0IeDS9K/2AA2RM2/jfaNdPKOG9NxoebbSCJ3nfrtZ4IgFzmAPDHdHIA8wGMJ9 +wk8iXjk053GezTy9iNNnkv/enjS8gUHVTZinsdhWGj0EPofk0gS6C4/BSLKp43ZO +muIpRAUf4tm99pGuTkXtroXQ+6GAGrbp+Be9qFpwLQX0iHwgZhcLIsbb3zHjba6x +kvZCUn+bK/fZiH8Bs1hXy/Yl265ravZIK50WdTrjtFBzi5vXHXeypmRefm+MB/qO +qLCYD2mJBfkHuYSiFmXeO+xAYRVzHfh8N5xXBRDauShENhLV2YaOTg0XDuqvHTy6 +CZdUtLh5F9qFewGYDusqr3jqVbIfw/dYwPgwxIgwhcr2qRM/HeaHdDlZSA== +-----END CERTIFICATE----- diff --git a/CPPCodeRespository/Lib/ssleay32MD.dll b/CPPCodeRespository/Lib/ssleay32MD.dll new file mode 100644 index 0000000..9fadfcf Binary files /dev/null and b/CPPCodeRespository/Lib/ssleay32MD.dll differ diff --git a/CPPCodeRespository/Lib/ssleay32MDd.dll b/CPPCodeRespository/Lib/ssleay32MDd.dll new file mode 100644 index 0000000..d8e2eb1 Binary files /dev/null and b/CPPCodeRespository/Lib/ssleay32MDd.dll differ diff --git a/CPPCodeRespository/LogWriter.h b/CPPCodeRespository/LogWriter.h index dbec68b..c641a52 100644 --- a/CPPCodeRespository/LogWriter.h +++ b/CPPCodeRespository/LogWriter.h @@ -1,6 +1,62 @@ #pragma once +//在 spdlog.h 之前定义,才有效 +#ifndef SPDLOG_TRACE_ON +#define SPDLOG_TRACE_ON +#endif + +#ifndef SPDLOG_DEBUG_ON +#define SPDLOG_DEBUG_ON +#endif #include "spdlog/spdlog.h" #include "spdlog/async.h" //support for async logging #include "spdlog/sinks/daily_file_sink.h" #include "spdlog/fmt/bin_to_hex.h" -using namespace spdlog; \ No newline at end of file +#include +using namespace spdlog; +class Logger +{ +public: + static Logger& GetInstance() { + static Logger m_instance; + return m_instance; + } + auto GetLogger() { return nml_logger; } +private: + Logger() + { + nml_logger = daily_logger_mt("Logger", "Log/Logger.log", 0, 0); + + // 设置日志记录级别 +#ifdef _DEBUG + nml_logger->set_level(spdlog::level::info); + nml_logger->flush_on(spdlog::level::info); +#else + nml_logger->set_level(spdlog::level::err); + nml_logger->flush_on(spdlog::level::err); +#endif + //spdlog::flush_every(std::chrono::seconds(3)); + } + ~Logger() { + spdlog::drop_all(); + } + Logger(const Logger&) = delete; + Logger& operator=(const Logger&) = delete; + +private: + std::shared_ptr nml_logger; +}; + +#define LogTrace(msg,...) Logger::GetInstance().GetLogger()->trace(suffix(msg),__VA_ARGS__) +#define LogDebug(...) Logger::GetInstance().GetLogger()->debug(__VA_ARGS__) +#define LogInfo(...) Logger::GetInstance().GetLogger()->info(__VA_ARGS__) +#define LogWarn(...) Logger::GetInstance().GetLogger()->warn(__VA_ARGS__) +#define LogError(...) Logger::GetInstance().GetLogger()->error(__VA_ARGS__) +#define LogCritical(...) Logger::GetInstance().GetLogger()->critical(__VA_ARGS__) + +#define criticalif(b, ...) \ + do { \ + if ((b)) { \ + Logger::GetInstance().GetLogger()->critical(__VA_ARGS__); \ + } \ + } while (0) + diff --git a/CPPCodeRespository/RightRefString.h b/CPPCodeRespository/RightRefString.h new file mode 100644 index 0000000..4f45894 --- /dev/null +++ b/CPPCodeRespository/RightRefString.h @@ -0,0 +1,100 @@ +#pragma once +#include "stdio.h" +#include +#include +using namespace std; + +class MyString +{ +public: + MyString() :m_pData(NULL), m_nLen(0) + { + cout << "MyString()" << endl; + } + MyString(const char *pStr) // 允许隐式转换 + { + cout << "MyString(const char *pStr)" << endl; + m_nLen = strlen(pStr); + CopyData(pStr); + } + MyString(const MyString& other) + { + cout << "MyString(const MyString& other)" << endl; + if (!other.m_pData) + { + m_nLen = other.m_nLen; + DeleteData(); + CopyData(other.m_pData); + } + } + MyString& operator=(const MyString& other) + { + cout << "MyString& operator=(const MyString& other)" << endl; + if (this != &other) + { + m_nLen = other.m_nLen; + DeleteData(); + CopyData(other.m_pData); + } + + return *this; + } + MyString(MyString&& other) + { + cout << "MyString(MyString&& other)" << endl; + m_nLen = other.m_nLen; + m_pData = other.m_pData; + other.m_pData = NULL; + } + MyString& operator=(MyString&& other) + { + cout << "MyString& operator=(const MyString&& other)" << endl; + if (this != &other) + { + m_nLen = other.m_nLen; + m_pData = other.m_pData; + other.m_pData = NULL; + } + return *this; + } + + ~MyString() + { + DeleteData(); + } + +private: + void CopyData(const char *pData) + { + if (pData) + { + m_pData = new char[m_nLen + 1]; + memcpy(m_pData, pData, m_nLen); + m_pData[m_nLen] = '\0'; + } + } + + void DeleteData() + { + if (m_pData != NULL) + { + delete[] m_pData; + m_pData = NULL; + } + } + +private: + char *m_pData; + size_t m_nLen; +}; +MyString Fun() +{ + MyString str = "hello world"; + return str; +} +static void Test() +{ + MyString str1 = "hello"; + MyString str2(str1); + MyString str3 = Fun(); +} diff --git a/CPPCodeRespository/SubjectCollection.h b/CPPCodeRespository/SubjectCollection.h new file mode 100644 index 0000000..7a00ea1 --- /dev/null +++ b/CPPCodeRespository/SubjectCollection.h @@ -0,0 +1,211 @@ +#include +#include"assert.h" +#include +#include"process.h" +class Singleton { +private: + Singleton() { + std::cout << std::endl; + std::cout << "Singleton()..." << std::endl; } + Singleton(const Singleton &) {} + Singleton & operator=(const Singleton& ) {} + +public: + ~Singleton() { + std::cout << std::endl; + std::cout << "~Singleton()..." << std::endl; } + static Singleton &getInstance() + { + static Singleton instance; + return instance; + } +}; + +unsigned int __stdcall threadFun(void *ptr) +{ + for (int num = 0; num < 10; num++) + { + std::cout << "Singleton::getInstance():" << &(Singleton::getInstance()) << std::endl; + } + return 0; +} +void SingleTest() +{ + for (int num = 0; num < 100; num++) + { + std::cout << "_beginthreadex: " << num << std::endl; + _beginthreadex(nullptr, 0, threadFun, nullptr, 0, nullptr); + } + +} +struct LinkNode { + int num; + LinkNode * next=nullptr; +}; +LinkNode * SingleLinkReverse(LinkNode * head) +{ + LinkNode * pNode = head; + LinkNode * pPrev = nullptr; + LinkNode * pNext = nullptr; + LinkNode * pReverseHerad = nullptr; + while (pNode != nullptr) + { + pNext = pNode->next; + if (pNext == nullptr) + pReverseHerad = pNode; + pNode->next = pPrev; + pPrev = pNode; + pNode = pNext; + } + return pReverseHerad; +} +LinkNode *SingleLinkCreate(int arr[],int length) +{ + LinkNode *link = new LinkNode; + LinkNode *pHead = link; + for(int i=0;inum = arr[i]; + + link->next = node; + link = link->next; + } + return pHead; +} +LinkNode * SingleLinkInsert(LinkNode * head,int num) +{ + LinkNode *pNode = head; + LinkNode * inNode = new LinkNode; + inNode->num = num; + LinkNode * prvNode = nullptr; + while (pNode != nullptr && inNode->num > pNode->num) + { + prvNode = pNode; + pNode = pNode->next; + } + if (pNode == nullptr) + { + prvNode->next = inNode; + } + else + { + prvNode->next = inNode; + inNode->next = pNode; + + } + return head; +} +LinkNode * SingleLinkInsertNode(LinkNode * head, int num) +{ + LinkNode * pNode = head; + + LinkNode * inNode = new LinkNode; + inNode->num = num; + inNode->next = nullptr; + + if (pNode == nullptr) + { + head = inNode; + } + else + { + while (pNode->next != nullptr) + { + pNode = pNode->next; + } + pNode->next = inNode; + } + return head; +} +LinkNode * SingleLinkDelete(LinkNode *head,int num) +{ + LinkNode * node = head; + LinkNode * pPrev = nullptr; + if (head == nullptr) + return nullptr; + if (node->num == num) + { + head = node->next; + delete node; + node = nullptr; + return head; + } + while (node != nullptr && node->num != num) + { + pPrev = node; + node = node->next; + } + if (node != nullptr) + { + LinkNode *delNode = node; + if (node->next != nullptr) + { + pPrev->next = node->next; + delete delNode; + } + else + { + pPrev->next = nullptr; + } + } + return head; +} +void TestLinkNode() +{ + LinkNode * node = SingleLinkInsertNode(nullptr, 100); + node = SingleLinkInsertNode(node, 101); + int arr[] = {0,4,8,12,16,20,24,28}; + LinkNode * link = SingleLinkCreate(arr,sizeof(arr)/sizeof(int)); + link = SingleLinkInsert(link, -1); + link = SingleLinkInsert(link, 1); + link = SingleLinkInsert(link, 1); + link = SingleLinkInsert(link, 3); + link = SingleLinkInsert(link, 30); + link = SingleLinkDelete(node, 101); + LinkNode * temp= SingleLinkReverse(link); + std::cout << std::endl; +} +char* mystrcpy(char* dst, const char* src) +{ + assert(dst != NULL); + assert(src != NULL); + + if (dst == src) + return dst; + + int size = strlen(src) + 1; + + if ((dst < src) || (src + size < dst)) + { + char* d = dst; + const char* s = src; + + while (size--) + *d++ = *s++; + } + else + { + char* d = dst + size - 1; + const char* s = src + size - 1; + + while (size--) + *d-- = *s--; + } + return dst; +} +void MySort(int arr[], int num) +{ + for (int i = 0; i < num; i++) + { + for (int j = 0; j < num; j++) + { + if (arr[j] > arr[j + 1]) + { + int temp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = arr[j]; + } + } + } +} \ No newline at end of file diff --git a/CPPCodeRespository/Tools/ucrtbased.dll b/CPPCodeRespository/Tools/ucrtbased.dll new file mode 100644 index 0000000..63efd91 Binary files /dev/null and b/CPPCodeRespository/Tools/ucrtbased.dll differ diff --git "a/CPPCodeRespository/Tools/\346\234\215\345\212\241\345\231\250\345\216\213\345\212\233\346\265\213\350\257\225\345\267\245\345\205\267.exe" "b/CPPCodeRespository/Tools/\346\234\215\345\212\241\345\231\250\345\216\213\345\212\233\346\265\213\350\257\225\345\267\245\345\205\267.exe" new file mode 100644 index 0000000..dbd9a28 Binary files /dev/null and "b/CPPCodeRespository/Tools/\346\234\215\345\212\241\345\231\250\345\216\213\345\212\233\346\265\213\350\257\225\345\267\245\345\205\267.exe" differ diff --git a/CPPCodeRespository/UnitTest.h b/CPPCodeRespository/UnitTest.h new file mode 100644 index 0000000..ac6285e --- /dev/null +++ b/CPPCodeRespository/UnitTest.h @@ -0,0 +1,144 @@ +#pragma once +#include "HttpClient.h" +#include "Base64Convert.h" +#include +#include"HttpServer.h" +#include"CPPEleven.h" +#include"LogWriter.h" +#include"WinIocpBase.h" +using namespace std; +void print(string out) +{ + cout << out << endl; +} +string getTime() +{ + char str[64]; + try + { + time_t timep; + time(&timep); + strftime(str, sizeof(str), "%Y-%m-%d %H:%M:%S", localtime(&timep)); + } + catch (std::exception e) + { + } + return str; +} + +void HttpCientTest() +{ + //HttpClient + HttpClient *client = new HttpClient(); + cout << getTime() << endl; + for (int i = 0; i < 1000; i++) + { + char temp[20]; + sprintf(temp, "1%018d", i); + string post_data = "" + string(temp) + "20191225105712251057孙洪英1112223334567896217000010005805406XSFDZDH34.201测试使用的商品名称10101010500000000003000.940.060.06金极为422010201709012004422010201709012004北京市海淀区 62436800海淀区西北旺建设银行支行 6243778866554433"; + string enc; + Base64Encode(post_data, enc); + client->SendReq("https://127.0.0.1:8888", print, "", enc); + } + delete client; + cout << getTime() << endl; +} +void HttpServerTest() +{ + HttpServer* httpsServer = new HttpServer(); + //HttpsTest + httpsServer->init("8888"); + httpsServer->startHttpService("server.pem","server.key"); + delete httpsServer; + + //多线程测试 + //MultiThreadStart(); +} +string base64TestInput = "2019123020191225105712251057孙洪英1112223334567896217000010005805406XSFDZDH34.201测试使用的商品名称10101010500000000003000.940.060.06金极为422010201709012004422010201709012004北京市海淀区 62436800海淀区西北旺建设银行支行 6243778866554433"; +void base64Test() +{ + string enc; + Base64Encode(base64TestInput, enc); + cout << enc; +} +void CppElevenTest() +{ + int num = sumnum(333, 222); +} +void LogWriterTest() +{ + for (int i=0;i<900000;i++) + { + LogInfo("Log writter test:{}" , i); + } +} +struct LinkNode +{ + LinkNode *Next; + int value; +}; +LinkNode * LinkReverse(LinkNode *pHead) +{ + LinkNode * pRevHead; + LinkNode * pNode = pHead; + LinkNode * pPre = nullptr; + while (pNode!=nullptr) + { + LinkNode * pNext = pNode->Next; + if (pNode->Next != nullptr) + pRevHead = pNode; + pNode->Next = pPre; + pPre = pNode; + pNode = pNext; + } + return pRevHead; +} +void TestReverse() +{ + LinkNode * link = new LinkNode; + LinkNode * head = link; + for (int i = 1; i < 10; i++) + { + link->value = i; + link->Next = new LinkNode; + link = link->Next; + } + link->Next = nullptr; + LinkNode* rev = LinkReverse(head); +} +int IOCPTest() +{ + CIOCPServer* pServer = new CIOCPServer; + + // 开启服务 + if (pServer->Start()) + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:Server start succussed on port:%d... \n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds, pServer->GetPort()); + } + else + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:Server start failed!\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds); + return 0; + } + + // 创建事件对象,让ServerShutdown程序能够关闭自己 + HANDLE hEvent = ::CreateEvent(NULL, FALSE, FALSE, L"ShutdownEvent"); + if (hEvent) + { + ::WaitForSingleObject(hEvent, INFINITE); + ::CloseHandle(hEvent); + } + + // 关闭服务 + pServer->Stop(); + delete pServer; + + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:Server Closed \n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds); + return 0; +} \ No newline at end of file diff --git a/CPPCodeRespository/WinIOCP.h b/CPPCodeRespository/WinIOCP.h new file mode 100644 index 0000000..b709bd6 --- /dev/null +++ b/CPPCodeRespository/WinIOCP.h @@ -0,0 +1,253 @@ +#pragma once +#ifndef _WINIOCP_INCLUDE_ +#define _WININCP_INCOUDE_ + +#include"winerror.h" +#include"Winsock2.h" +#pragma comment(lib, "ws2_32") +#include"windows.h" +#include +using namespace std; + +/// 宏定义 +#define PORT 5050 +#define DATA_BUFSIZE 8192 + +#define OutErr(a) cout << (a) << endl \ + << "出错代码:"<< WSAGetLastError() << endl \ + << "出错文件:"<< __FILE__ << endl \ + << "出错行数:"<< __LINE__ << endl \ + +#define OutMsg(a) cout << (a) << endl; + + +/// 全局函数定义 + + +/////////////////////////////////////////////////////////////////////// +// +// 函数名 : InitWinsock +// 功能描述 : 初始化WINSOCK +// 返回值 : void +// +/////////////////////////////////////////////////////////////////////// +void InitWinsock() +{ + // 初始化WINSOCK + WSADATA wsd; + if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0) + { + OutErr("WSAStartup()"); + } +} + +/////////////////////////////////////////////////////////////////////// +// +// 函数名 : BindServerOverlapped +// 功能描述 : 绑定端口,并返回一个 Overlapped 的ListenSocket +// 参数 : int nPort +// 返回值 : SOCKET +// +/////////////////////////////////////////////////////////////////////// +SOCKET BindServerOverlapped(int nPort) +{ + // 创建socket 注意里面有个WSA_FLAG_OVERLAPPED参数 只有在服务器端需要这么做,在客户端是不需要的 + SOCKET sServer = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); + + // 绑定端口 + struct sockaddr_in servAddr; + servAddr.sin_family = AF_INET; + servAddr.sin_port = htons(nPort); + servAddr.sin_addr.s_addr = htonl(INADDR_ANY); + + if (::bind(sServer, (struct sockaddr*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) + { + OutErr("bind Failed!"); + return NULL; + } + + // 设置监听队列为200 + if (listen(sServer, 200) != 0) + { + OutErr("listen Failed!"); + return NULL; + } + return sServer; +} + + +/// 结构体定义 +typedef struct +{ + OVERLAPPED Overlapped; + WSABUF DataBuf; + CHAR Buffer[DATA_BUFSIZE]; +}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA; + + +typedef struct +{ + SOCKET Socket; +}PER_HANDLE_DATA, *LPPER_HANDLE_DATA; + + +DWORD WINAPI ProcessIO(LPVOID lpParam) +{ + HANDLE CompletionPort = (HANDLE)lpParam; + DWORD BytesTransferred; + LPPER_HANDLE_DATA PerHandleData; + LPPER_IO_OPERATION_DATA PerIoData; + + while (true) + { + + if (0 == GetQueuedCompletionStatus(CompletionPort, &BytesTransferred, (LPDWORD)&PerHandleData, (LPOVERLAPPED*)&PerIoData, INFINITE)) + { + if ((GetLastError() == WAIT_TIMEOUT) || (GetLastError() == ERROR_NETNAME_DELETED)) + { + cout << "closingsocket" << PerHandleData->Socket << endl; + closesocket(PerHandleData->Socket); + + delete PerIoData; + delete PerHandleData; + continue; + } + else + { + OutErr("GetQueuedCompletionStatus failed!"); + } + return 0; + } + + // 说明客户端已经退出 + if (BytesTransferred == 0) + { + cout << "closing socket" << PerHandleData->Socket << endl; + closesocket(PerHandleData->Socket); + delete PerIoData; + delete PerHandleData; + continue; + } + + // 取得数据并处理 + cout << PerHandleData->Socket << "发送过来的消息:" << PerIoData->Buffer << endl; + + // 继续向 socket 投递WSARecv操作 + DWORD Flags = 0; + DWORD dwRecv = 0; + ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA)); + PerIoData->DataBuf.buf = PerIoData->Buffer; + PerIoData->DataBuf.len = DATA_BUFSIZE; + WSARecv(PerHandleData->Socket, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); + } + + return 0; +} +#include +#include +#define MAXCNT 30000 +void WinIOCPClient() +{ + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData);//WSAStartup()加载套接字库 + if (err != 0) { + + return; + } + + if (LOBYTE(wsaData.wVersion) != 2 || + HIBYTE(wsaData.wVersion) != 2) { + WSACleanup(); + return; + } + + static int nCnt = 0; + char sendBuf[2000]; + // char recvBuf[100]; + while (nCnt < MAXCNT) + { + SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0); + SOCKADDR_IN addrSrv; + addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//本地回路地址127,用于一台机器上测试的IP + addrSrv.sin_family = AF_INET; + addrSrv.sin_port = htons(5050);//和服务器端的端口号保持一致 + connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));//连接服务器端(套接字,地址转换,长度) + + + sprintf(sendBuf, "This is TestNo : %d\n", ++nCnt); + send(sockClient, sendBuf, strlen(sendBuf) + 1, 0);//向服务器端发送数据,"+1"是为了给'\0'留空间 + printf("send:%s", sendBuf); + + // memset(recvBuf,0,100); + // recv(sockClient,recvBuf,100,0);//接收数据 + // printf("%s\n",recvBuf);//打印 + + closesocket(sockClient);//关闭套接字,释放为这个套接字分配的资源 + Sleep(1); + } + WSACleanup();//终止对这个套接字库的使用 +} +void WinIOCPServer() +{ + InitWinsock(); + HANDLE CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + + //根据系统的CPU来创建工作者线程 + SYSTEM_INFO SystemInfo; + GetSystemInfo(&SystemInfo); + + //线程数目=系统进程数目的两倍. + for (int i = 0; i Socket = sClient; + + // 将接入的客户端和完成端口联系起来 + CreateIoCompletionPort((HANDLE)sClient, CompletionPort, (DWORD)PerHandleData, 0); + + // 建立一个Overlapped,并使用这个Overlapped结构对socket投递操作 + PerIoData = new PER_IO_OPERATION_DATA(); + + ZeroMemory(PerIoData, sizeof(PER_IO_OPERATION_DATA)); + PerIoData->DataBuf.buf = PerIoData->Buffer; + PerIoData->DataBuf.len = DATA_BUFSIZE; + + // 投递一个WSARecv操作 + DWORD Flags = 0; + DWORD dwRecv = 0; + WSARecv(sClient, &PerIoData->DataBuf, 1, &dwRecv, &Flags, &PerIoData->Overlapped, NULL); + } + + DWORD dwByteTrans; + //将一个已经完成的IO通知添加到IO完成端口的队列中. + //提供了与线程池中的所有线程通信的方式. + PostQueuedCompletionStatus(CompletionPort, dwByteTrans, 0, 0); //IO操作完成时接收的字节数. + + closesocket(sListen); +} +#endif \ No newline at end of file diff --git a/CPPCodeRespository/WinIocpBase.cpp b/CPPCodeRespository/WinIocpBase.cpp new file mode 100644 index 0000000..aea87a0 --- /dev/null +++ b/CPPCodeRespository/WinIocpBase.cpp @@ -0,0 +1,483 @@ +#include "stdafx.h" +#include "WinIocpBase.h" +#include + +#pragma comment(lib, "WS2_32.lib") + +IOContextPool SocketContext::ioContextPool; // 初始化 + +IOCPBase::IOCPBase() : + completionPort(INVALID_HANDLE_VALUE), + workerThreads(NULL), + workerThreadNum(0), + IP(L"127.0.0.1"), + port(10240), + listenSockContext(NULL), + fnAcceptEx(NULL), + fnGetAcceptExSockAddrs(NULL), + connectCnt(0), + acceptPostCnt(0) +{ + WSADATA wsaData; + WSAStartup(MAKEWORD(2, 2), &wsaData); + stopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); +} + + +IOCPBase::~IOCPBase() +{ + RELEASE_HANDLE(stopEvent); + Stop(); + WSACleanup(); +} + + +BOOL IOCPBase::Start(int port, int maxConn, int maxIOContextInPool, int maxSocketContextInPool) +{ + if (false == InitializeIOCP()) + return false; + + if (false == InitializeListenSocket()) + { + DeInitialize(); + return false; + } + + return true; +} + +void IOCPBase::Stop() +{ + if (listenSockContext != NULL && listenSockContext->connSocket != INVALID_SOCKET) + { + // 激活关闭事件 + SetEvent(stopEvent); + + for (int i = 0; i < workerThreadNum; i++) + { + // 通知所有完成端口退出 + PostQueuedCompletionStatus(completionPort, 0, (DWORD)EXIT_CODE, NULL); + } + + // 等待所有工作线程退出 + WaitForMultipleObjects(workerThreadNum, workerThreads, TRUE, INFINITE); + + // 释放其他资源 + DeInitialize(); + } +} + +BOOL IOCPBase::SendData(SocketContext* socketContext, char* data, int size) +{ + return 0; +} + +wstring IOCPBase::GetLocalIP() +{ + //char hostName[MAX_PATH] = { 0 }; + //gethostname(hostName, MAX_PATH); + //struct hostent FAR *hostent = gethostbyname(hostName); + //if (hostent == NULL) + //{ + // return string(DEFAULT_IP); + //} + + //// 取得IP地址列表中的第一个为返回的IP(因为一台主机可能会绑定多个IP) + //char *addr = hostent->h_addr_list[0]; + //in_addr inAddr; + //memmove(&inAddr, addr, 4); + + //return string(inet_ntoa(inAddr)); + return wstring(DEFAULT_IP); +} + +BOOL IOCPBase::InitializeIOCP() +{ + completionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); + if (NULL == completionPort) + { + return false; + } + + workerThreadNum = WORKER_THREADS_PER_PROCESSOR * GetNumOfProcessors(); + workerThreads = new HANDLE[workerThreadNum]; + + for (int i = 0; i < workerThreadNum; i++) + { + workerThreads[i] = CreateThread(0, 0, WorkerThreadProc, (void*)this, 0, 0); + } + return true; +} + +BOOL IOCPBase::InitializeListenSocket() +{ + // 生成用于监听的socket的Context + listenSockContext = new SocketContext; + listenSockContext->connSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); + if (INVALID_SOCKET == listenSockContext->connSocket) + return false; + + // 将socket绑定到完成端口中 + if (NULL == CreateIoCompletionPort((HANDLE)listenSockContext->connSocket, completionPort, (DWORD)listenSockContext, 0)) + { + RELEASE_SOCKET(listenSockContext->connSocket); + return false; + } + + //服务器地址信息,用于绑定socket + sockaddr_in serverAddr; + + // 填充地址信息 + ZeroMemory((char*)&serverAddr, sizeof(serverAddr)); + serverAddr.sin_family = AF_INET; + serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); + serverAddr.sin_port = htons(port); + + // 绑定地址和端口 + if (SOCKET_ERROR == bind(listenSockContext->connSocket, (sockaddr*)&serverAddr, sizeof(serverAddr))) + { + return false; + } + + // 开始监听 + if (SOCKET_ERROR == listen(listenSockContext->connSocket, SOMAXCONN)) + { + return false; + } + + GUID guidAcceptEx = WSAID_ACCEPTEX; + GUID guidGetAcceptSockAddrs = WSAID_GETACCEPTEXSOCKADDRS; + // 提取扩展函数指针 + DWORD dwBytes = 0; + if (SOCKET_ERROR == WSAIoctl( + listenSockContext->connSocket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &guidAcceptEx, + sizeof(guidAcceptEx), + &fnAcceptEx, + sizeof(fnAcceptEx), + &dwBytes, + NULL, + NULL)) + { + DeInitialize(); + return false; + } + + if (SOCKET_ERROR == WSAIoctl( + listenSockContext->connSocket, + SIO_GET_EXTENSION_FUNCTION_POINTER, + &guidGetAcceptSockAddrs, + sizeof(guidGetAcceptSockAddrs), + &fnGetAcceptExSockAddrs, + sizeof(fnGetAcceptExSockAddrs), + &dwBytes, + NULL, + NULL)) + { + DeInitialize(); + return false; + } + + for (size_t i = 0; i < MAX_POST_ACCEPT; i++) + { + IOContext* ioContext = listenSockContext->GetNewIOContext(); + if (false == PostAccept(listenSockContext, ioContext)) + { + listenSockContext->RemoveContext(ioContext); + return false; + } + } + return true; +} + +void IOCPBase::DeInitialize() +{ + // 关闭系统退出事件句柄 + RELEASE_HANDLE(stopEvent); + + // 释放工作者线程句柄指针 + for (int i = 0; i < workerThreadNum; i++) + { + RELEASE_HANDLE(workerThreads[i]); + } + + RELEASE(workerThreads); + + // 关闭IOCP句柄 + RELEASE_HANDLE(completionPort); + + // 关闭监听Socket + RELEASE(listenSockContext); +} + +BOOL IOCPBase::IsSocketAlive(SOCKET sock) +{ + int nByteSent = send(sock, "", 0, 0); + if (-1 == nByteSent) + return false; + return true; +} + +int IOCPBase::GetNumOfProcessors() +{ + SYSTEM_INFO si; + GetSystemInfo(&si); + return si.dwNumberOfProcessors; +} + +BOOL IOCPBase::AssociateWithIOCP(SocketContext* sockContext) +{ + // 将用于和客户端通信的SOCKET绑定到完成端口中 + HANDLE hTemp = CreateIoCompletionPort((HANDLE)sockContext->connSocket, completionPort, (DWORD)sockContext, 0); + + if (NULL == hTemp) + { + return false; + } + + return true; +} + +BOOL IOCPBase::PostAccept(SocketContext* sockContext, IOContext* ioContext) +{ + DWORD dwBytes = 0; + ioContext->ioType = ACCEPT_POSTED; + ioContext->ioSocket = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED); + if (INVALID_SOCKET == ioContext->ioSocket) + { + return false; + } + + // 将接收缓冲置为0,令AcceptEx直接返回,防止拒绝服务攻击 + if (false == fnAcceptEx(listenSockContext->connSocket, ioContext->ioSocket, ioContext->wsaBuf.buf, 0, sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, &dwBytes, &ioContext->overLapped)) + { + if (WSA_IO_PENDING != WSAGetLastError()) + { + return false; + } + } + + InterlockedIncrement(&acceptPostCnt); + return true; +} + +BOOL IOCPBase::PostRecv(SocketContext* sockContext, IOContext* ioContext) +{ + DWORD dwFlags = 0, dwBytes = 0; + ioContext->Reset(); + ioContext->ioType = RECV_POSTED; + + int nBytesRecv = WSARecv(ioContext->ioSocket, &ioContext->wsaBuf, 1, &dwBytes, &dwFlags, &ioContext->overLapped, NULL); + // 如果返回值错误,并且错误的代码并非是Pending的话,那就说明这个重叠请求失败了 + if ((SOCKET_ERROR == nBytesRecv) && (WSA_IO_PENDING != WSAGetLastError())) + { + DoClose(sockContext); + return false; + } + return true; +} + +BOOL IOCPBase::PostSend(SocketContext* sockContext, IOContext* ioContext) +{ + ioContext->ioType = SEND_POSTED; + DWORD dwBytes = 0, dwFlags = 0; + + if (::WSASend(ioContext->ioSocket, &ioContext->wsaBuf, 1, &dwBytes, dwFlags, &ioContext->overLapped, NULL) != NO_ERROR) + { + if (WSAGetLastError() != WSA_IO_PENDING) + { + DoClose(sockContext); + return false; + } + } + return true; +} + +BOOL IOCPBase::DoAccpet(SocketContext* sockContext, IOContext* ioContext) +{ + + InterlockedIncrement(&connectCnt); + InterlockedDecrement(&acceptPostCnt); + SOCKADDR_IN* clientAddr = NULL; + SOCKADDR_IN* localAddr = NULL; + int clientAddrLen, localAddrLen; + clientAddrLen = localAddrLen = sizeof(SOCKADDR_IN); + + // 1. 获取地址信息 (GetAcceptExSockAddrs函数不仅可以获取地址信息,还可以顺便取出第一组数据) + fnGetAcceptExSockAddrs(ioContext->wsaBuf.buf, 0, localAddrLen, clientAddrLen, (LPSOCKADDR*)&localAddr, &localAddrLen, (LPSOCKADDR*)&clientAddr, &clientAddrLen); + + // 2. 为新连接建立一个SocketContext + SocketContext* newSockContext = new SocketContext; + newSockContext->connSocket = ioContext->ioSocket; + memcpy_s(&(newSockContext->clientAddr), sizeof(SOCKADDR_IN), clientAddr, sizeof(SOCKADDR_IN)); + + // 3. 将listenSocketContext的IOContext 重置后继续投递AcceptEx + ioContext->Reset(); + if (false == PostAccept(listenSockContext, ioContext)) + { + listenSockContext->RemoveContext(ioContext); + } + + // 4. 将新socket和完成端口绑定 + if (NULL == CreateIoCompletionPort((HANDLE)newSockContext->connSocket, completionPort, (DWORD)newSockContext, 0)) + { + DWORD dwErr = WSAGetLastError(); + if (dwErr != ERROR_INVALID_PARAMETER) + { + DoClose(newSockContext); + return false; + } + } + + // 并设置tcp_keepalive + tcp_keepalive alive_in; + tcp_keepalive alive_out; + alive_in.onoff = TRUE; + alive_in.keepalivetime = 1000 * 60; // 60s 多长时间( ms )没有数据就开始 send 心跳包 + alive_in.keepaliveinterval = 1000 * 10; //10s 每隔多长时间( ms ) send 一个心跳包 + unsigned long ulBytesReturn = 0; + if (SOCKET_ERROR == WSAIoctl(newSockContext->connSocket, SIO_KEEPALIVE_VALS, &alive_in, sizeof(alive_in), &alive_out, sizeof(alive_out), &ulBytesReturn, NULL, NULL)) + { + TRACE(L"WSAIoctl failed: %d/n", WSAGetLastError()); + } + + + OnConnectionEstablished(newSockContext); + + // 5. 建立recv操作所需的ioContext,在新连接的socket上投递recv请求 + IOContext* newIoContext = newSockContext->GetNewIOContext(); + newIoContext->ioType = RECV_POSTED; + newIoContext->ioSocket = newSockContext->connSocket; + // 投递recv请求 + if (false == PostRecv(newSockContext, newIoContext)) + { + DoClose(sockContext); + return false; + } + + return true; +} + +BOOL IOCPBase::DoRecv(SocketContext* sockContext, IOContext* ioContext) +{ + OnRecvCompleted(sockContext, ioContext); + ioContext->Reset(); + if (false == PostRecv(sockContext, ioContext)) + { + DoClose(sockContext); + return false; + } + return true; +} + +BOOL IOCPBase::DoSend(SocketContext* sockContext, IOContext* ioContext) +{ + OnSendCompleted(sockContext, ioContext); + return 0; +} + +BOOL IOCPBase::DoClose(SocketContext* sockContext) +{ + InterlockedDecrement(&connectCnt); + RELEASE(sockContext); + return true; +} + +DWORD IOCPBase::WorkerThreadProc(LPVOID lpParam) +{ + IOCPBase* iocp = (IOCPBase*)lpParam; + OVERLAPPED* ol = NULL; + SocketContext* sockContext; + DWORD dwBytes = 0; + IOContext* ioContext = NULL; + + while (WAIT_OBJECT_0 != WaitForSingleObject(iocp->stopEvent, 0)) + { + BOOL bRet = GetQueuedCompletionStatus(iocp->completionPort, &dwBytes, (PULONG_PTR)&sockContext, &ol, INFINITE); + + // 读取传入的参数 + ioContext = CONTAINING_RECORD(ol, IOContext, overLapped); + + // 收到退出标志 + if (EXIT_CODE == (DWORD)sockContext) + { + break; + } + + if (!bRet) + { + DWORD dwErr = GetLastError(); + + // 如果是超时了,就再继续等吧 + if (WAIT_TIMEOUT == dwErr) + { + // 确认客户端是否还活着... + if (!iocp->IsSocketAlive(sockContext->connSocket)) + { + iocp->OnConnectionClosed(sockContext); + + // 回收socket + iocp->DoClose(sockContext); + continue; + } + else + { + continue; + } + } + // 可能是客户端异常退出了(64) + else if (ERROR_NETNAME_DELETED == dwErr) + { + iocp->OnConnectionError(sockContext, dwErr); + + // 回收socket + iocp->DoClose(sockContext); + continue; + } + else + { + iocp->OnConnectionError(sockContext, dwErr); + + // 回收socket + iocp->DoClose(sockContext); + continue; + } + } + else + { + // 判断是否有客户端断开 + if ((0 == dwBytes) && (RECV_POSTED == ioContext->ioType || SEND_POSTED == ioContext->ioType)) + { + iocp->OnConnectionClosed(sockContext); + + // 回收socket + iocp->DoClose(sockContext); + continue; + } + else + { + switch (ioContext->ioType) + { + case ACCEPT_POSTED: + iocp->DoAccpet(sockContext, ioContext); + break; + case RECV_POSTED: + iocp->DoRecv(sockContext, ioContext); + break; + case SEND_POSTED: + iocp->DoSend(sockContext, ioContext); + break; + default: + break; + } + } + } + } + + // 释放线程参数 + RELEASE(lpParam); + return 0; +} + + diff --git a/CPPCodeRespository/WinIocpBase.h b/CPPCodeRespository/WinIocpBase.h new file mode 100644 index 0000000..6cbe9e6 --- /dev/null +++ b/CPPCodeRespository/WinIocpBase.h @@ -0,0 +1,365 @@ +/* +========================================================================== +* 这个类CIOCPModel是本代码的核心类,用于说明WinSock服务器端编程模型中的完成端口(IOCP)的使用方法 + +* 其中的IOContext类是封装了用于每一个重叠操作的参数 + +* 具体说明了服务器端建立完成端口、建立工作者线程、投递Recv请求、投递Accept请求的方法,所有的客户端连入的Socket都需要绑定到IOCP上,所有从客户端发来的数据,都会调用回调函数。 + +*用法:派生一个子类,重载回掉函数 +========================================================================== +*/ +#pragma once + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +//使用系统安全字符串函数支持 +#include +//使用ATL的字符集转换支持 +#include + +using std::vector; +using std::list; +using std::wstring; + +#define BUFF_SIZE (1024*4) // I/O 请求的缓冲区大小 +#define WORKER_THREADS_PER_PROCESSOR (2) // 每个处理器上的线程数 +#define MAX_POST_ACCEPT (10) // 同时投递的Accept数量 +#define INIT_IOCONTEXT_NUM (100) // IOContextPool中的初始数量 +#define EXIT_CODE (-1) // 传递给Worker线程的退出信号 +#define DEFAULT_IP (L"127.0.0.1") // 默认IP地址 +#define DEFAULT_PORT (10240) // 默认端口 + +// 释放指针的宏 +#define RELEASE(x) {if(x != NULL) {delete x; x = NULL;}} +// 释放句柄的宏 +#define RELEASE_HANDLE(x) {if(x != NULL && x != INVALID_HANDLE_VALUE) { CloseHandle(x); x = INVALID_HANDLE_VALUE; }} +// 释放Socket的宏 +#define RELEASE_SOCKET(x) {if(x != INVALID_SOCKET) { closesocket(x); x = INVALID_SOCKET; }} + +#ifndef TRACE +#include + +#define TRACE AtlTrace +#define TRACE0(f) TRACE(f) +#define TRACE1(f, p1) TRACE(f, p1) +#define TRACE2(f, p1, p2) TRACE(f, p1, p2) +#define TRACE3(f, p1, p2, p3) TRACE(f, p1, p2, p3) +#define TRACE4(f, p1, p2, p3, p4) TRACE(f, p1, p2, p3, p4) +#define TRACE5(f, p1, p2, p3, p4, p5) TRACE(f, p1, p2, p3, p4, p5) +#endif + +enum IO_OPERATION_TYPE +{ + NULL_POSTED, // 用于初始化,无意义 + ACCEPT_POSTED, // 投递Accept操作 + SEND_POSTED, // 投递Send操作 + RECV_POSTED, // 投递Recv操作 +}; + +class IOContext +{ +public: + WSAOVERLAPPED overLapped; // 每个socket的每一个IO操作都需要一个重叠结构 + SOCKET ioSocket; // 此IO操作对应的socket + WSABUF wsaBuf; // 数据缓冲 + IO_OPERATION_TYPE ioType; // IO操作类型 + UINT connectID; // 连接ID + + IOContext() + { + ZeroMemory(&overLapped, sizeof(overLapped)); + ioSocket = INVALID_SOCKET; + wsaBuf.buf = (char*)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BUFF_SIZE); + wsaBuf.len = BUFF_SIZE; + ioType = NULL_POSTED; + connectID = 0; + } + + ~IOContext() + { + RELEASE_SOCKET(ioSocket); + + if (wsaBuf.buf != NULL) + ::HeapFree(::GetProcessHeap(), 0, wsaBuf.buf); + } + + void Reset() + { + if (wsaBuf.buf != NULL) + ZeroMemory(wsaBuf.buf, BUFF_SIZE); + else + wsaBuf.buf = (char*)::HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, BUFF_SIZE); + ZeroMemory(&overLapped, sizeof(overLapped)); + ioType = NULL_POSTED; + connectID = 0; + } +}; + +// 空闲的IOContext管理类(IOContext池) +class IOContextPool +{ +private: + list contextList; + CRITICAL_SECTION csLock; + +public: + IOContextPool() + { + InitializeCriticalSection(&csLock); + contextList.clear(); + + EnterCriticalSection(&csLock); + for (size_t i = 0; i < INIT_IOCONTEXT_NUM; i++) + { + IOContext* context = new IOContext; + contextList.push_back(context); + } + LeaveCriticalSection(&csLock); + + } + + ~IOContextPool() + { + EnterCriticalSection(&csLock); + for (list::iterator it = contextList.begin(); it != contextList.end(); it++) + { + delete (*it); + } + contextList.clear(); + LeaveCriticalSection(&csLock); + + DeleteCriticalSection(&csLock); + } + + // 分配一个IOContxt + IOContext* AllocateIoContext() + { + IOContext* context = NULL; + + EnterCriticalSection(&csLock); + if (contextList.size() > 0) //list不为空,从list中取一个 + { + context = contextList.back(); + contextList.pop_back(); + } + else //list为空,新建一个 + { + context = new IOContext; + } + LeaveCriticalSection(&csLock); + + return context; + } + + // 回收一个IOContxt + void ReleaseIOContext(IOContext* pContext) + { + pContext->Reset(); + EnterCriticalSection(&csLock); + contextList.push_front(pContext); + LeaveCriticalSection(&csLock); + } +}; + +class SocketContext +{ +public: + SOCKET connSocket; // 连接的socket + SOCKADDR_IN clientAddr; // 连接的远程地址 + +private: + vector arrIoContext; // 同一个socket上的多个IO请求 + static IOContextPool ioContextPool; // 空闲的IOContext池 + CRITICAL_SECTION csLock; + +public: + SocketContext() + { + InitializeCriticalSection(&csLock); + arrIoContext.clear(); + connSocket = INVALID_SOCKET; + ZeroMemory(&clientAddr, sizeof(clientAddr)); + } + + ~SocketContext() + { + RELEASE_SOCKET(connSocket); + + // 回收所有的IOContext + for (vector::iterator it = arrIoContext.begin(); it != arrIoContext.end(); it++) + { + ioContextPool.ReleaseIOContext(*it); + } + + EnterCriticalSection(&csLock); + arrIoContext.clear(); + LeaveCriticalSection(&csLock); + + DeleteCriticalSection(&csLock); + } + + // 获取一个新的IoContext + IOContext* GetNewIOContext() + { + IOContext* context = ioContextPool.AllocateIoContext(); + if (context != NULL) + { + EnterCriticalSection(&csLock); + arrIoContext.push_back(context); + LeaveCriticalSection(&csLock); + } + return context; + } + + // 从数组中移除一个指定的IoContext + void RemoveContext(IOContext* pContext) + { + for (vector::iterator it = arrIoContext.begin(); it != arrIoContext.end(); it++) + { + if (pContext == *it) + { + ioContextPool.ReleaseIOContext(*it); + + EnterCriticalSection(&csLock); + arrIoContext.erase(it); + LeaveCriticalSection(&csLock); + + break; + } + } + } + + // +}; + +// IOCP基类 +class IOCPBase +{ +public: + IOCPBase(); + ~IOCPBase(); + + // 开始服务 + BOOL Start(int port = 10240, int maxConn = 2000, int maxIOContextInPool = 256, + int maxSocketContextInPool = 200); + // 停止服务 + void Stop(); + // 向指定客户端发送数据 + BOOL SendData(SocketContext* socketContext, char* data, int size); + + // 获取本机的IP + wstring GetLocalIP(); + + // 获取当前连接数 + ULONG GetConnectCnt() { return connectCnt; } + + // 获取当前连接数 + UINT GetPort() { return port; } + + // 事件通知函数(派生类重载此族函数) + // 新连接 + virtual void OnConnectionEstablished(SocketContext* sockContext) = 0; + // 连接关闭 + virtual void OnConnectionClosed(SocketContext* sockContext) = 0; + // 连接上发生错误 + virtual void OnConnectionError(SocketContext* sockContext, int error) = 0; + // 读操作完成 + virtual void OnRecvCompleted(SocketContext* sockContext, IOContext* ioContext) = 0; + // 写操作完成 + virtual void OnSendCompleted(SocketContext* sockContext, IOContext* ioContext) = 0; + +protected: + HANDLE stopEvent; // 通知线程退出的时间 + HANDLE completionPort; // 完成端口 + HANDLE* workerThreads; // 工作者线程的句柄指针 + int workerThreadNum; // 工作者线程的数量 + wstring IP; // 本地IP + int port; // 监听端口 + SocketContext* listenSockContext; // 监听socket的Context + LONG connectCnt; // 当前的连接数量 + LONG acceptPostCnt; // 当前投递的的Accept数量 + + LPFN_ACCEPTEX fnAcceptEx; //AcceptEx函数指针 + //GetAcceptExSockAddrs;函数指针 + LPFN_GETACCEPTEXSOCKADDRS fnGetAcceptExSockAddrs; + +private: + static DWORD WINAPI WorkerThreadProc(LPVOID lpParam); // 工作线程函数 + + // 初始化IOCP + BOOL InitializeIOCP(); + // 初始化Socket + BOOL InitializeListenSocket(); + // 释放资源 + void DeInitialize(); + // socket是否存活 + BOOL IsSocketAlive(SOCKET sock); + // 获取本机CPU核心数 + int GetNumOfProcessors(); + // 将句柄(Socket)绑定到完成端口中 + BOOL AssociateWithIOCP(SocketContext* sockContext); + // 投递IO请求 + BOOL PostAccept(SocketContext* sockContext, IOContext* ioContext); + BOOL PostRecv(SocketContext* sockContext, IOContext* ioContext); + BOOL PostSend(SocketContext* sockContext, IOContext* ioContext); + + // IO处理函数 + BOOL DoAccpet(SocketContext* sockContext, IOContext* ioContext); + BOOL DoRecv(SocketContext* sockContext, IOContext* ioContext); + BOOL DoSend(SocketContext* sockContext, IOContext* ioContext); + BOOL DoClose(SocketContext* sockContext); +}; + +class CIOCPServer : public IOCPBase +{ +public: + // 新连接 + void OnConnectionEstablished(SocketContext* sockContext) + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:Accept a connection,Current connects:%d\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds, GetConnectCnt()); + } + + // 连接关闭 + void OnConnectionClosed(SocketContext* sockContext) + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:A connection had closed,Current connects:%d\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds, GetConnectCnt()); + } + + // 连接上发生错误 + void OnConnectionError(SocketContext* sockContext, int error) + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:A connection erro: %d,Current connects:%d\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds, error, GetConnectCnt()); + } + + // 读操作完成 + void OnRecvCompleted(SocketContext* sockContext, IOContext* ioContext) + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:Recv data: %s \n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds, ioContext->wsaBuf.buf); + } + // 写操作完成 + void OnSendCompleted(SocketContext* sockContext, IOContext* ioContext) + { + SYSTEMTIME sys; + GetLocalTime(&sys); + printf("%4d-%02d-%02d %02d:%02d:%02d.%03d:Send data successd!\n", sys.wYear, sys.wMonth, sys.wDay, sys.wHour, sys.wMinute, sys.wSecond, sys.wMilliseconds); + } + +}; \ No newline at end of file diff --git a/CPPCodeRespository/WinService.h b/CPPCodeRespository/WinService.h new file mode 100644 index 0000000..076454a --- /dev/null +++ b/CPPCodeRespository/WinService.h @@ -0,0 +1,352 @@ +#pragma once +//服务控制函数 +#include +#include "tlhelp32.h" +#include "stdio.h" +#include "tchar.h " +//全局变量 +SERVICE_STATUS ssStatus; // 当前服务的状态 +DWORD dwErr = 0; // 错误码 +HANDLE hServerStopEvent = NULL; // 服务停用事件 +SERVICE_STATUS_HANDLE sshStatusHandle; // 服务状态控制句柄 +HANDLE hRpcThdHandle = NULL; // Rpc服务虚拟化接收线程 + +#define SZ_SERVICE_NAME L"ServiceTest" +#define SZ_SERVICE_DISPLAY_NAME L"ServiceTestForDisplay" + +//服务入口 +void ServiceInit(const char **argv) +{ + SERVICE_TABLE_ENTRY dispatchTable[] = + { + { (LPWSTR)L"SZ_SERVICE_NAME", (LPSERVICE_MAIN_FUNCTION)ServiceMain },{ NULL, NULL } + }; + if (_stricmp(argv[1], "-service") == 0) + { + CmdInstallService(); + return; + } + else if (_stricmp(argv[1], "-remove") == 0) + { + CmdRemoveService(); + return; + } + StartServiceCtrlDispatcher(dispatchTable); +} +//移除服务 +void CmdRemoveService() +{ + SC_HANDLE schService, schSCManager; + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + if (schSCManager) + { + schService = OpenService(schSCManager, SZ_SERVICE_NAME, SERVICE_ALL_ACCESS); + if (schService) + { + // try to stop the service + if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) + { + OutputDebugStringW(L"\nStopping FVM Controller Service."); + Sleep(1000); + + while (QueryServiceStatus(schService, &ssStatus)) + { + if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) + { + OutputDebugStringW(L"."); + Sleep(1000); + } + else + { + break; + } + } + + if (ssStatus.dwCurrentState == SERVICE_STOPPED) + { + OutputDebugStringW(L"\nController Service stopped.\n"); + } + else + { + OutputDebugStringW(L"\nFailed to stop Controller Service.\n"); + } + } + + // now remove the service + if (DeleteService(schService)) + { + OutputDebugStringW(L"Controller Service removed.\n"); + } + else + { + OutputDebugStringW(L"Delete Controller Service failed.\n"); + } + + CloseServiceHandle(schService); + } + else + { + OutputDebugStringW(L"Open Controller Service failed.\n"); + } + + CloseServiceHandle(schSCManager); + } + else + { + OutputDebugStringW(L"Open SCManager failed.\n"); + } +} + +//启动服务 +VOID CmdStartService(SC_HANDLE hservice) +{ + if (!StartService(hservice, 0, NULL)) + { + OutputDebugStringW(L"\nStarting FVM Controller Service failed.\n"); + return; + } + + OutputDebugStringW(L"Starting Controller Service."); + Sleep(1000); + + while (QueryServiceStatus(hservice, &ssStatus)) + { + if (ssStatus.dwCurrentState == SERVICE_START_PENDING) + { + OutputDebugStringW(L"."); + Sleep(1000); + } + else + { + break; + } + } + + if (ssStatus.dwCurrentState == SERVICE_RUNNING) + OutputDebugStringW(L"\nController Service started.\n"); + else + OutputDebugStringW(L"\nFailed to start Controller Service.\n"); +} + +//安装服务 +void CmdInstallService() +{ + SC_HANDLE schService; + SC_HANDLE schSCManager; + WCHAR szPath[MAX_PATH]; + WCHAR szQuotePath[MAX_PATH + 1]; + + SERVICE_DESCRIPTION szDiscription; + + if (GetModuleFileName(NULL, szPath, MAX_PATH) == 0) + { + OutputDebugStringW(L"Unable to install Controller Service.\n"); + return; + } + wsprintf(szQuotePath, L"\"%s\"", szPath); + + schSCManager = OpenSCManager( + NULL, // machine (NULL == local) + NULL, // database (NULL == default) + SC_MANAGER_ALL_ACCESS // access required + ); + if (schSCManager) + { + schService = CreateService( + schSCManager, // SCManager database + SZ_SERVICE_NAME, // name of service + SZ_SERVICE_DISPLAY_NAME, // name to display + SERVICE_ALL_ACCESS, // desired access + SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS, + SERVICE_AUTO_START, + SERVICE_ERROR_NORMAL, // error control type + szQuotePath, // service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL/*SZ_DEPENDS_SERVICE_NAME*/, // dependencies + NULL, // LocalSystem account + NULL); // no password + + if (schService) + { + szDiscription.lpDescription =(LPWSTR) SZ_SERVICE_DISPLAY_NAME; + ChangeServiceConfig2(schService, SERVICE_CONFIG_DESCRIPTION, &szDiscription); + + OutputDebugStringW(L"Controller Service installed.\n"); + CmdStartService(schService); + CloseServiceHandle(schService); + } + else + { + OutputDebugStringW(L"Installing Controller Service failed.\n"); + } + + CloseServiceHandle(schSCManager); + } + else + OutputDebugStringW(L"Open SCManager failed.\n"); +} + + +//服务入口函数 +VOID WINAPI ServiceMain(DWORD dwArgc, LPCWSTR *lpszArgv) +{ + // register our service control handler: + sshStatusHandle = RegisterServiceCtrlHandler(L"SZ_SERVICE_NAME", ServiceCtrl); + + ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + ssStatus.dwServiceSpecificExitCode = 0; + + // report the status to the service control manager. + if (!ReportStatusToSCMgr(SERVICE_START_PENDING, NO_ERROR, 3000)) + { + if (sshStatusHandle) + (VOID)ReportStatusToSCMgr(SERVICE_STOPPED, dwErr, 0); + } + + ServiceStart(dwArgc, lpszArgv); + + // try to report the stopped status to the service control manager. + if (sshStatusHandle) + (VOID)ReportStatusToSCMgr(SERVICE_STOPPED, dwErr, 0); +} + +VOID WINAPI ServiceCtrl(DWORD dwCtrlCode) +{ + // Handle the requested control code. + switch (dwCtrlCode) + { + + /* 停止服务时,需要所有的沙化进程全部结束 */ + case SERVICE_CONTROL_STOP: + { + ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0); + ServiceStop(); + } + return; + + // Update the service status. + case SERVICE_CONTROL_INTERROGATE: + break; + + // invalid control code + // + default: + break; + } + ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); +} +// 向 SCM 报告服务状态 +BOOL ReportStatusToSCMgr(DWORD dwCurrentState, + DWORD dwWin32ExitCode, + DWORD dwWaitHint) +{ + static DWORD dwCheckPoint = 1; + BOOL fResult = TRUE; + + if (dwCurrentState == SERVICE_START_PENDING) + ssStatus.dwControlsAccepted = 0; + else + ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + ssStatus.dwCurrentState = dwCurrentState; + ssStatus.dwWin32ExitCode = dwWin32ExitCode; + ssStatus.dwWaitHint = dwWaitHint; + + if ((dwCurrentState == SERVICE_RUNNING) || + (dwCurrentState == SERVICE_STOPPED)) + ssStatus.dwCheckPoint = 0; + else + ssStatus.dwCheckPoint = dwCheckPoint++; + + // Report the status of the service to the service control manager. + fResult = SetServiceStatus(sshStatusHandle, &ssStatus); + + return fResult; +} + +//服务实际功能执行区 +VOID ServiceStart(DWORD dwArgc, LPCWSTR *lpszArgv) +{ + // create the event object. The control handler function signals + // this event when it receives the "stop" control code. + + hServerStopEvent = CreateEvent( + NULL, // no security attributes + TRUE, // manual reset event + FALSE, // not-signalled + NULL); // no name + + // report the status to the service control manager. + if (!ReportStatusToSCMgr(SERVICE_RUNNING, NO_ERROR, 0)) + { + if (hServerStopEvent) + CloseHandle(hServerStopEvent); + return; + } + + BOOL bRet = FALSE; + bRet = PreRun(); + + WaitForSingleObject(hServerStopEvent, INFINITE); + + //cleanup: + if (hServerStopEvent) + CloseHandle(hServerStopEvent); +} + +//停止服务 +VOID ServiceStop() +{ + if (hServerStopEvent) + { + KillProcessByName(L"twaina.exe"); + SetEvent(hServerStopEvent); + } +} +//执行服务需要做的事情 +bool PreRun() +{ + +} +static BOOL KillProcessByName(const TCHAR *lpszProcessName) { + unsigned int pid = -1; + BOOL retval = TRUE; + + if (lpszProcessName == NULL) + return -1; + + DWORD dwRet = 0; + HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + PROCESSENTRY32 processInfo; + processInfo.dwSize = sizeof(PROCESSENTRY32); + int flag = Process32First(hSnapshot, &processInfo); + + // Find the process with name as same as lpszProcessName + while (flag != 0) + { + if (_tcscmp(processInfo.szExeFile, lpszProcessName) == 0) { + // Terminate the process. + pid = processInfo.th32ProcessID; + HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, TRUE, pid); + + if (TerminateProcess(hProcess, 0) != TRUE) { // Failed to terminate it. + retval = FALSE; + break; + } + } + + flag = Process32Next(hSnapshot, &processInfo); + } // while (flag != 0) + + CloseHandle(hSnapshot); + + if (pid == -1) + return FALSE; + + return retval; +} \ No newline at end of file