端口池(C++)
端口池
对齐有点乱,可以复制到自己的IDE自动对齐
PortPool.h
/************************************************************************** * * Copyright (C) 2022 * All rights reserved * * Filename : WLPortPool.h * Description : 动态端口已占用完毕的情况下,获取动态端口的函数接口。 * Environment : 由于动态端口资源耗尽,导致主机卫士的curl无法通信,WLPortPool * 可以在该情况下启动端口扫描的线程,在动态端口不满足()的情况下,创建端口池 * (STU_PORT_POOL)。curl可以在此环境下调用此函数提供的接口获取系统当前可用端口。 * * Detail : 接口命名空间(WNTPORT)。 * 1. 使用时需先开启端口池扫描线程 createScanPortsThread,该线程需调用 killScanPortsThread 关闭 * 2. 启动线程后,通过全局变量 WNTPORT::g_bFlagGetStaticPort 或者 getPortPoolStatus() 查看当前端口池状态 * 3. 根据第2步的状态选择是否需要获取端口池,如需,调用 getPort() * Created by mingming.shi on Jan. 24th, 2022 * *************************************************************************/ #pragma once #include <iostream> #include <stdio.h> #include <string.h> #include <string> #include <vector> #include <sstream> #include <windows.h> #include <WinSock.h> #include <tcpmib.h> #include <IPHlpApi.h> #include <set> #include "../include/curl/include/curl.h" #include "..\common\WLNetCommApi.h" #pragma comment(lib, "WS2_32.lib") #pragma comment(lib, "IPHlpApi.lib") #define MAX_PORT_NUM 10 // 默认端口池的数量 #define DEFAULT_START_PORT 1025 // 默认启动端口 #define DEFAULT_STOP_PORT 65535 // 默认终止端口 #define DEFAULT_PORT_RANGE 100 // 默认端口范围 #define DEFAULT_MIN_PORTRANGE 50 // 默认最小端口范围 #define START_STATIC_PORT_FLAG 100 // FLAG:当系统可用动态端口个数小于该值时,启用端口池 /* 端口池结构体 */ typedef struct _PORT_POOL { UINT nStartPort; // 启动端口 UINT nRange; // 端口范围 bool bEnable; // 保留:当前端口是否可用,用于回调接口时用户自行设置。false表示不可用 _PORT_POOL(UINT nSta = 0, UINT nRan = 0, bool bEn = false):nStartPort(nSta),nRange(nRan),bEnable(bEn){}; bool isContain(UINT uPORT) { if ( uPORT >= nStartPort && uPORT < (nStartPort + nRange) ) { return true; } return false; } bool isLegal() { if( (this->nStartPort + this->nRange) <= DEFAULT_STOP_PORT && (this->nStartPort) >= DEFAULT_START_PORT ) { return true; } return false; } bool operator<(const _PORT_POOL& b) const { return this->nStartPort == b.nStartPort ? this->nRange <= b.nRange : this->nStartPort < b.nRange; } }STU_PORT_POOL, *PSTU_PORT_POOL; /* (端口池) */ extern std::vector<STU_PORT_POOL> g_stuPortPool; #ifdef __cplusplus extern "C" { #endif namespace WNTPORT { extern bool g_bFlagGetStaticPort; // 端口池是否启用。 [true:表示已经启用端口池] extern bool g_bStartThread; // 端口检测线程是否开启。 [true:表示已经启动端口检测线程] extern int g_nCurPoint; // 端口池轮询 extern HANDLE g_hEvent; // 端口池检测线程的控制句柄 /* 端口池线程 */ void createScanPortsThread(); /* 杀死线程 */ void killScanPortsThread(); #if 0 /* WLNetCommApi */ #endif /* 设置当前端口状态 */ void WINAPI setPortIsAvailable(__in STU_PORT_POOL stuPort); /* 返回一个可用端口和其范围 */ void WINAPI getPort(__out STU_PORT_POOL& stuPort); /* 返回端口池状态 */ bool WINAPI getPortPoolStatus(); /* 设置 curl 的启动端口和范围 */ int WINAPI setCurlPort(CURL *curl); /* 设置 socket 的本地端口 */ int WINAPI setSocketPort(SOCKADDR_IN *socket); } #ifdef __cplusplus } #endif
PortPool.cpp
/************************************************************************** * * Copyright (C) 2022 Beijing * All rights reserved * * Filename : WLPortPool.cpp * Description : 动态端口已占用完毕的情况下,获取动态端口的函数接口实现文件,详看头文件声明 * * Created by mingming.shi on Jan. 24th, 2022 * *************************************************************************/ #include "StdAfx.h" #include "WLPortPool.h" #include <process.h> #define STU_MEMBER_NUM 2 #define CMD_RESULT_BUF_SIZE 1024 #define TIME_SCAN_FREQUENCY 1000 * 30 #define CMD_QUERY_DYNAMIC_TCPPORT "netsh int ipv4 show dynamicport tcp" std::vector<STU_PORT_POOL> g_stuPortPool; bool WNTPORT::g_bFlagGetStaticPort = false; bool WNTPORT::g_bStartThread = false; int WNTPORT::g_nCurPoint = 0; HANDLE WNTPORT::g_hEvent = NULL; #if 0 /* 内部函数声明 */ #endif /************************************************************************/ /* 其他函数声明 2022-1-24 14:33:28 */ /************************************************************************/ // 获取动态端口 int executeCMD(__out char *pChRet); int getDynamicPortFromstr(__out STU_PORT_POOL& stuDynamicPort); // 获取当前已占用端口 int getAllTcpConnectionsPort(__out std::set<UINT>& setRet); // 获取剩余端口 int getFreeDynamicPort(__in STU_PORT_POOL stuDynamicPort, __in std::set<UINT> CurSysUsedPort, __out std::vector<STU_PORT_POOL>& stuFreeDynamicPort); int getFreeStaticPort(__in STU_PORT_POOL stuDynamicPort, __in std::set<UINT> CurSysUsedPort, __out std::vector<STU_PORT_POOL>& stuFreeStaticPort); // 更新端口 void updatePort(__in __out std::vector<STU_PORT_POOL>::iterator it); // 创建端口池 int createPortPool(); // 获取剩余动态端口数量 int getFreeDynamicPortsNum(__out int& nNum); // 线程:获取系统当前剩余动态端口数量 unsigned int WINAPI scanSysDynamicPortsNum(void* lpParam); #if 0 /* 对外接口定义 */ #endif /* * @fn createScanPortsThread * @brief 启动端口检测线程,设置 g_bStartThread 句柄控制端口池线程的状态 * @param[in] * @param[out] * @return * * @detail 调用 killScanPortsThread 关闭端口扫描线程 * @author mingming.shi * @date 2022-1-27 */ void WNTPORT::createScanPortsThread() { if( false == g_bStartThread ) { HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, scanSysDynamicPortsNum, 0, 0, NULL); if (NULL == hThread) { WriteError(_T("Create scanSysDynamicPortsNum thread error. [%d]"), GetLastError()); g_bStartThread = false; return; } WriteInfo(_T("Create scanSysDynamicPortsNum thread SUCCESS. ")); g_hEvent = CreateEvent(NULL, TRUE, FALSE, TEXT("PortPool")); CloseHandle(hThread); g_bStartThread = true; } } /* * @fn killScanPortsThread * @brief 杀死扫描动态端口的线程 * @param[in] * @param[out] * @return * * @detail * @author mingming.shi * @date 2022-1-28 */ void WNTPORT::killScanPortsThread() { SetEvent(g_hEvent); WriteInfo(_T("LINE [%d] killScanPortsThread"), __LINE__); return; } /* * @fn getPort * @brief 返回一个可用端口和其范围(同时供 WLNetCommApi 使用) * @param[in] * @param[out] STU_PORT_POOL: 返回一个可用端口,如果调用失败,则修改stuPort中的BEnable为false * @return 0表示成功;其他表示失败 * * @detail 依次返回端口池中的端口和范围 * @author mingming.shi * @date 2022-1-24 */ void WINAPI WNTPORT::getPort(__out STU_PORT_POOL& stuPort) { int iRet = -1; std::vector<STU_PORT_POOL>::iterator it = g_stuPortPool.begin(); if ( 0 == g_stuPortPool.size() ) // 当前端口池为空 { iRet = createPortPool(); if (NO_ERROR != iRet) { WriteError(_T("LINE [%d] Create Port Pool FAILED!"), __LINE__); return; } } it = g_stuPortPool.begin(); for (int i = 0; it != g_stuPortPool.end(); it++) { if (false == it->isLegal()) { updatePort(it); } if ( true == it->bEnable && // 当前端口可用 true == it->isLegal() && // 当前端口合法 i == g_nCurPoint % 10) // 轮询 { STU_PORT_POOL stuTemp; stuTemp = *it; stuPort.nStartPort = stuTemp.nStartPort; stuPort.nRange = stuTemp.nRange; stuPort.bEnable = stuTemp.bEnable; g_nCurPoint++; if (g_nCurPoint >= INT_MAX) { g_nCurPoint = 0; } break; } i++; } } /* * @fn setPortIsAvailable * @brief 设置当前端口的可用状态(同时供 WLNetCommApi 使用) * @param[in] STU_PORT_POOL: 需要删除的端口 * @param[out] * @return * * @detail 会根据当前的启动端口和范围在端口池中查找一致的并删除,然后立即更新端口池 * 【改接口保留,但目前未使用】 * @author mingming.shi * @date 2022-1-24 */ void WINAPI WNTPORT::setPortIsAvailable(__in STU_PORT_POOL stuPort) { std::vector<STU_PORT_POOL>::iterator it = g_stuPortPool.begin(); for (; it != g_stuPortPool.end(); it++) { if (it->nStartPort == stuPort.nStartPort && it->nRange == stuPort.nRange && stuPort.bEnable == false) // 当前端口不可用 { // g_stuPortPool.erase(it); // 目前不移除 break; } } updatePort(it); } /* * @fn getPortPoolStatus * @brief 获取端口池启用状态(同时供 WLNetCommApi 使用) * @param[in] * @param[out] * @return true表示已经启用端口池 * * @detail * @author mingming.shi * @date 2022-1-28 */ bool WINAPI WNTPORT::getPortPoolStatus() { return g_bFlagGetStaticPort; } /* * @fn setCurlPort * @brief 设置Curl的启动端口和范围 * @param[in] curl:需要设置端口的CURL对象 * @param[out] curl:设置了启动端口和范围的CURL对象 * @return 0表示成功;其他表示失败 * * @detail * @author mingming.shi * @date 2022-2-10 */ int WINAPI WNTPORT::setCurlPort(__in __out CURL *curl) { int iRet = 0; std::set<UINT> CurSysUsedPort; STU_PORT_POOL stuAllPortRange; STU_PORT_POOL stuSet2CurlPort; // 1 获取端口占用情况 iRet = getAllTcpConnectionsPort(CurSysUsedPort); if(NO_ERROR != iRet) { iRet = -1; goto _END_; } // 2 从未占用的端口中获取一个启动地址和范围 stuAllPortRange.nStartPort = DEFAULT_START_PORT; stuAllPortRange.nRange = DEFAULT_STOP_PORT; for (UINT nPort = DEFAULT_START_PORT; nPort != DEFAULT_STOP_PORT; ++nPort) { if ( CurSysUsedPort.end() == CurSysUsedPort.find(nPort) && true == stuAllPortRange.isContain(nPort) ) // 找到了未使用端口,并且不在动态端口范围内 { int nRange = 0; // 遍历当前启动端口的端口范围 do { nRange++; }while ( CurSysUsedPort.end() == CurSysUsedPort.find(nPort + nRange) // 系统未使用 && nRange < DEFAULT_PORT_RANGE); // 范围小于默认端口范围 stuSet2CurlPort.nStartPort = nPort; stuSet2CurlPort.nRange = nRange >= DEFAULT_MIN_PORTRANGE ? nRange : DEFAULT_MIN_PORTRANGE; } } // 3 设置curl的启动端口和范围 curl_easy_setopt(curl, CURLOPT_LOCALPORT, stuPort.nStartPort); curl_easy_setopt(curl, CURLOPT_LOCALPORTRANGE, stuPort.nRange); iRet = 0; _END_: return iRet; } /* * @fn setSocketPort * @brief 绑定一个本地可用端口到socket * @param[in] socket:需要绑定本地端口的socket * @param[out] socket:绑定了本地端口的socket * @return 0表示成功;其他表示失败 * * @detail * @author mingming.shi * @date 2022-2-10 */ int WINAPI WNTPORT::setSocketPort(__in __out SOCKADDR_IN *socket) { int iRet; int iBindRet; SOCKADDR_IN myaddr; std::set<UINT> CurSysUsedPort; UINT nPort = DEFAULT_START_PORT; // 1 获取端口占用情况 iRet = getAllTcpConnectionsPort(CurSysUsedPort); if(NO_ERROR != iRet) { iRet = -1; goto _END_; } // 2 从未占用的端口中获取一个可用端口并设置 for ( nPort != DEFAULT_STOP_PORT; ++nPort) { if ( CurSysUsedPort.end() == CurSysUsedPort.find(nPort) && true == stuAllPortRange.isContain(nPort) ) // 找到了未使用端口,并且不在动态端口范围内 { break; } } // 绑定 nPort 到 sokcet myaddr.sin_port = htons(nPort); myaddr.sin_addr.s_addr = INADDR_ANY; myaddr.sin_family = AF_INET; iBindRet = bind(m_Socket, (SOCKADDR*)&myaddr, sizeof( struct sockaddr)); if (iBindRet < 0) { iRet = -2; goto _END_; } _END_: return iRet; } #if 0 /* 内部函数定义 */ #endif /* * @fn CreatPortPool * @brief 创建端口资源池 * @param[in] * @param[out] * @return 0:成功;其他:表示失败 * * @detail 当系统动态端口使用情况不满足IEG时调用此接口获取静态端口资源池,保存到 g_stuPortPool 变量中 * @author mingming.shi * @date 2022-1-24 */ int createPortPool() { int iRet = 0; std::vector<STU_PORT_POOL> stuPortPool; // 保存接口返回的端口范围 std::vector<STU_PORT_POOL> stuFreeDynamicPort; // 保存未被使用端口范围 STU_PORT_POOL stuDynamicPort; std::set<UINT> CurSysUsedPort; // 1 获取动态端口状态(起始地址和范围) iRet = getDynamicPortFromstr(stuDynamicPort); if(NO_ERROR != iRet) { iRet = -1; goto _END_; } // 2 获取端口占用情况 iRet = getAllTcpConnectionsPort(CurSysUsedPort); if(NO_ERROR != iRet) { iRet = -2; goto _END_; } // 3 从默认地址开始查找可用端口范围 iRet = getFreeStaticPort(stuDynamicPort, CurSysUsedPort, stuFreeDynamicPort); if(NO_ERROR == iRet) { g_stuPortPool = stuFreeDynamicPort; } iRet = 0; _END_: return iRet; } /* * @fn ExecuteCMD * @brief 执行查询TCP动态端口命令,获取系统动态端口范围 * @param[in] * @param[out] pChRet: 命令行执行后的输出字符串 * @return 0 表示成功;其他 失败 * * @detail * @author mingming.shi * @date 2022-1-24 */ static int executeCMD(__out char *pChRet) { int iRet = -1; char buf_ps[CMD_RESULT_BUF_SIZE]; char pChBuf[CMD_RESULT_BUF_SIZE] = { 0 }; FILE *ptr; strcpy_s(pChBuf, _countof(CMD_QUERY_DYNAMIC_TCPPORT) ,CMD_QUERY_DYNAMIC_TCPPORT); if ( NULL != (ptr = _popen(pChBuf, "r")) ) { while (NULL != fgets(buf_ps, sizeof(buf_ps), ptr) ) { strcat_s(pChRet, _countof(buf_ps), buf_ps); if (strlen(pChRet) > CMD_RESULT_BUF_SIZE) { iRet = -2; break; } } _pclose(ptr); ptr = NULL; iRet = 0; // 处理成功 } else { WriteError(_T("popen %s error\n"), pChBuf); iRet = -1; // 处理失败 } return iRet; } /* * @fn getDynamicPortFromstr * @brief 从cmd命令的输出中获取动态端口的启动地址和范围 * @param[in] * @param[out] stuDynamicPort: 动态端口的起始地址和范围 * @return 0 表示成功,其他表示失败 * * @detail 该动态端口为TCP端口 * @author mingming.shi * @date 2022-1-24 */ int getDynamicPortFromstr(__out STU_PORT_POOL& stuDynamicPort) { int iRet = 0; size_t nStrLen = 0; std::string strCmdRet = ""; std::vector<unsigned int> vecNumFromStr; char chRet[CMD_RESULT_BUF_SIZE] = { 0 }; // 1 执行CMD获取其输出,格式如下 /* 协议 tcp 动态端口范围 --------------------------------- 启动端口 : 49152 端口数 : 16384 */ iRet = executeCMD(chRet); if ( NO_ERROR != iRet ) { iRet = -1; goto _END_; } strCmdRet = chRet; // char to string if(strCmdRet.empty()) { iRet = -2; goto _END_; } // 2 获取CMD输出中的数字 nStrLen = strCmdRet.length(); for (size_t i = 0; i < nStrLen; i++) { int CurNum = 0; bool flag = false; while ( !(strCmdRet[i] >= '0' && strCmdRet[i] <= '9') && i < nStrLen ) // 遍历到数字 { i++; } while ( (strCmdRet[i] >= '0' && strCmdRet[i] <= '9') && i < nStrLen ) // 遍历到字母 { flag = true; CurNum = CurNum * 10 + (strCmdRet[i] - '0'); i++; } if (flag) { vecNumFromStr.push_back(CurNum); } } if (STU_MEMBER_NUM != vecNumFromStr.size()) { iRet = -3; goto _END_; } stuDynamicPort.nStartPort = vecNumFromStr[0]; stuDynamicPort.nRange = vecNumFromStr[1]; iRet = 0; _END_: return iRet; //集合大小就是不同整数数量 } /* * @fn getAllTcpConnectionsPort * @brief 获取已连接端口数 * @param[in] * @param[out] ret:已连接端口的set容器 * @return 0 表示执行成功,其他表示失败 * * @detail * @author mingming.shi * @date 2022-1-24 */ int getAllTcpConnectionsPort(__out std::set<UINT>& setRet) { int iRet = 0; int nNum = 0; // TCP连接的数目 std::set<UINT> setPort; PMIB_TCPTABLE_OWNER_PID pTcpTable(NULL); DWORD dwSize(0); GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0); pTcpTable = (MIB_TCPTABLE_OWNER_PID *)new char[dwSize];//重新分配缓冲区 if ( NO_ERROR != GetExtendedTcpTable(pTcpTable, &dwSize, TRUE, AF_INET, TCP_TABLE_OWNER_PID_ALL, 0) ) { delete pTcpTable; pTcpTable = NULL; { iRet = -1; goto _END_; } } // TCP连接的数目 nNum = (int)pTcpTable->dwNumEntries; for (int i = 0; i < nNum; i++) { setPort.insert(htons((u_short)pTcpTable->table[i].dwLocalPort)); } setRet = setPort; _END_: if (pTcpTable != NULL) { free(pTcpTable); pTcpTable = NULL; } return iRet; } /* * @fn getFreeDynamicPort * @brief 获取未被占用的动态端口段 * @param[in] stuDynamicPort:系统当前开放的动态端口范围 CurSysUsedPort:系统当前已使用端口 * @param[out] stuFreeStaticPort: 从默认端口开始获取的端口范围 * @return * * @detail * @author mingming.shi * @date 2022-1-24 */ int getFreeDynamicPort(__in STU_PORT_POOL stuDynamicPort, __in std::set<UINT> CurSysUsedPort, __out std::vector<STU_PORT_POOL>& stuFreeDynamicPort) { int iRet = 0; UINT nStart = stuDynamicPort.nStartPort; UINT nEnd = stuDynamicPort.nStartPort + stuDynamicPort.nRange; for (UINT nPort = nStart; nPort != nEnd; ++nPort) { STU_PORT_POOL stuTempPort; if ( CurSysUsedPort.end() != CurSysUsedPort.find(nPort) ) // 找到了未使用端口 { int nRange = 0; // 遍历当前启动端口的端口范围 while ( CurSysUsedPort.end() != CurSysUsedPort.find( nPort + nRange) ) { nRange++; } stuTempPort.nStartPort = nPort; stuTempPort.nRange = nRange; } stuFreeDynamicPort.push_back(stuTempPort); if (stuFreeDynamicPort.size() > MAX_PORT_NUM) { iRet = -1; goto _END_; } } _END_: return iRet; } /* * @fn getFreeStaticPort * @brief 从默认端口开始获取未被系统使用的静态端口和范围 * @param[in] stuDynamicPort:系统当前开放的动态端口范围 CurSysUsedPort:系统当前已使用端口 * @param[out] stuFreeStaticPort: 返回 * @return 0 表示成功,其他表示失败 * * @detail * @author mingming.shi * @date 2022-1-24 */ int getFreeStaticPort(__in STU_PORT_POOL stuDynamicPort, __in std::set<UINT> CurSysUsedPort, __out std::vector<STU_PORT_POOL>& stuFreeStaticPort) { int iRet = -1; UINT nStart = DEFAULT_START_PORT; UINT nEnd = DEFAULT_STOP_PORT; for (UINT nPort = nStart; nPort != nEnd; ++nPort) { STU_PORT_POOL stuTempPort; if ( CurSysUsedPort.end() == CurSysUsedPort.find(nPort) && false == stuDynamicPort.isContain(nPort) ) // 找到了未使用端口,并且不在动态端口范围内 { int nRange = 0; // 遍历当前启动端口的端口范围 do { nRange++; }while ( CurSysUsedPort.end() == CurSysUsedPort.find(nPort + nRange) && // 系统未使用 false == stuDynamicPort.isContain(nPort + nRange) && // 不在动态端口范围 nRange < DEFAULT_PORT_RANGE); // 范围小于默认端口范围 stuTempPort.nStartPort = nPort; stuTempPort.nRange = nRange >= DEFAULT_MIN_PORTRANGE ? nRange : DEFAULT_MIN_PORTRANGE; stuTempPort.bEnable = true; // 更新启动端口并检查合法性 nPort += nRange; nPort = nPort >= DEFAULT_STOP_PORT ? DEFAULT_START_PORT : nPort; } stuFreeStaticPort.push_back(stuTempPort); if (stuFreeStaticPort.size() >= MAX_PORT_NUM) // 只是数组满了而已,仍然返回成功 { iRet = 0; goto _END_; } } iRet = 0; _END_: return iRet; } /* * @fn getFreeDynamicPortsNum * @brief 获取剩余动态端口数量 * @param[in] * @param[out] nNum:系统空闲动态端口数量 * @return 0 表示成功,其他表示失败 * * @detail * @author mingming.shi * @date 2022-1-24 */ int getFreeDynamicPortsNum(__out int& nNum) { int iRet = 0; int nPortsNum = 0; STU_PORT_POOL stuDynamicPort; std::set<UINT> CurSysUsedPort; std::set<UINT>::iterator it; // 1 获取动态端口状态(起始地址和范围) iRet = getDynamicPortFromstr(stuDynamicPort); if ( NO_ERROR != iRet ) { iRet = -1; goto _END_; } // 2 获取当前系统端口占用情况 iRet = getAllTcpConnectionsPort(CurSysUsedPort); if ( NO_ERROR != iRet ) { iRet = -2; goto _END_; } // 3 统计动态端口个数 for (it = CurSysUsedPort.begin(); it != CurSysUsedPort.end(); it++) { if(true == stuDynamicPort.isContain(*it)) { nPortsNum++; } } nNum = stuDynamicPort.nRange - nPortsNum; iRet = 0; _END_: if (CurSysUsedPort.size()) { CurSysUsedPort.clear(); } return iRet; } /* * @fn updatePort * @brief 端口池更新:更新一个端口到端口池中 * @param[in] * @param[out] * @return * * @detail * @author mingming.shi * @date 2022-1-27 */ void updatePort(__in __out std::vector<STU_PORT_POOL>::iterator it) { UINT nStart = DEFAULT_START_PORT; UINT nEnd = DEFAULT_STOP_PORT; STU_PORT_POOL stuDynamicPort; std::set<UINT> CurSysUsedPort; std::vector<STU_PORT_POOL>::reverse_iterator itPortPoolEnd = g_stuPortPool.rbegin(); // 1 获取动态端口状态(起始地址和范围) getDynamicPortFromstr(stuDynamicPort); // 2 获取端口占用情况 getAllTcpConnectionsPort(CurSysUsedPort); // 3 更新启动端口,从端口池最后一个端口开始 if (true == itPortPoolEnd->isLegal()) { nStart = itPortPoolEnd->nStartPort > DEFAULT_START_PORT ? itPortPoolEnd->nStartPort : DEFAULT_START_PORT; } else { nStart = DEFAULT_START_PORT; } // 4 寻找可用端口和范围 for (UINT nPort = nStart; nPort <= DEFAULT_STOP_PORT; ++nPort) { STU_PORT_POOL stuTempPort; if ( CurSysUsedPort.end() != CurSysUsedPort.find(nPort) && false == stuDynamicPort.isContain(nPort) ) // 找到了未使用端口,并且不再动态端口范围内 { int nRange = 0; // 遍历当前启动端口的端口范围 while ( CurSysUsedPort.end() != CurSysUsedPort.find(nPort + nRange) && false == stuDynamicPort.isContain(nPort + nRange) ) { nRange++; if (nRange >= DEFAULT_PORT_RANGE) { break; } } stuTempPort.nStartPort = nPort; stuTempPort.nRange = nRange; stuTempPort.bEnable = true; // 更新启动端口并检查合法性 nPort += nRange; nPort = nPort >= DEFAULT_STOP_PORT ? DEFAULT_START_PORT : nPort; } if (true == stuTempPort.isLegal()) { it->nStartPort = stuTempPort.nStartPort; it->nRange = stuTempPort.nRange; it->bEnable = stuTempPort.bEnable; } if (g_stuPortPool.size() > MAX_PORT_NUM) { break; } } } /* * @fn scanSysDynamicPortsNum * @brief 扫描系统当前剩余动态端口数量 * @param[in] * @param[out] * @return * * @detail * @author mingming.shi * @date 2022-1-27 */ unsigned int WINAPI scanSysDynamicPortsNum(void* lpParam) { int iRet = -1; while(1) { int nDynamicNum = INT_MAX; //step1: 执行动态端口扫描流程,获取 启动端口 和 范围 if ( NO_ERROR != getFreeDynamicPortsNum(nDynamicNum) ) { WriteInfo(_T("LINE [%d] PortPool Get Dynamic Port Number Failed!\n"), __LINE__); iRet = -1; goto _END_; } //step2:判断当前可用动态端口是否需要启用端口池 if (START_STATIC_PORT_FLAG >= nDynamicNum) { // WriteInfo(_T("LINE [%d] PortPool Start Get Static Port!\n"), __LINE__); iRet = createPortPool(); if (NO_ERROR != iRet) { WriteInfo(_T("LINE [%d] PortPool Create Static PortPool FAILED!\n"), __LINE__); iRet = -2; goto _END_;// } WNTPORT::g_bFlagGetStaticPort = true; } else { WNTPORT::g_bFlagGetStaticPort = false; } //step3: 等待停止线程信号,每30s执行一次 DWORD dwRet = WaitForSingleObject(WNTPORT::g_hEvent, TIME_SCAN_FREQUENCY); switch (dwRet) { case WAIT_OBJECT_0: // hProcess所代表的进程在 TIME_SCAN_FREQUENCY 秒内结束 iRet = 0; WNTPORT::g_bStartThread = false; WNTPORT::g_bFlagGetStaticPort = false; // TODO WriteInfo(_T("LINE [%d] PortPool killed PortPool SUCCESS!\n"), __LINE__); goto _END_; case WAIT_TIMEOUT: // 等待时间超过5秒,暂不处理 break; case WAIT_FAILED: // 函数调用失败,比如传递了一个无效的句柄 WriteError(_T("LINE [%d] PortPool killed PortPool FAILED!\n"), __LINE__); break; } iRet = 0; } _END_: return iRet; }
本文来自博客园,作者:StimuMing,转载请注明原文链接:https://www.cnblogs.com/fole-del/p/15878920.html
分类:
,
标签:
,
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步