CreateIoCompletionPort

本文详细介绍了如何使用CreateIoCompletionPort函数创建I/O完成端口并将其与文件句柄关联,以实现异步I/O操作的高效处理。涵盖了函数的参数解释、返回值说明及使用注意事项。

创建输入/输出(I / O)完成端口并将其与指定的文件句柄相关联,或创建尚未与文件句柄相关联的I / O完成端口,从而允许以后进行关联。

将打开的文件句柄的实例与I / O完成端口相关联,可使进程接收有关该文件句柄的异步I / O操作完成的通知。

 注意

此处使用的术语文件句柄是指表示重叠的I / O端点的系统抽象,而不仅仅是磁盘上的文件。任何支持重叠I / O的系统对象(例如网络端点,TCP套接字,命名管道和邮件插槽)都可以用作文件句柄。有关更多信息,请参见“备注”部分。

句法
C ++


HANDLE WINAPI CreateIoCompletionPort(
  _In_     HANDLE    FileHandle,
  _In_opt_ HANDLE    ExistingCompletionPort,
  _In_     ULONG_PTR CompletionKey,
  _In_     DWORD     NumberOfConcurrentThreads
);


参量
FileHandle [输入]

打开的文件句柄或INVALID_HANDLE_VALUE。

该句柄必须指向支持重叠I / O的对象。

如果提供了句柄,则必须打开它才能完成I / O重叠。例如,在使用CreateFile函数获取句柄时,必须指定FILE_FLAG_OVERLAPPED标志。

如果指定了INVALID_HANDLE_VALUE,该函数将创建一个I / O完成端口,而不将其与文件句柄关联。在这种情况下,ExistingCompletionPort参数必须为NULL,并且CompletionKey参数将被忽略。

ExistingCompletionPort [in,可选]

现有I / O完成端口或NULL的句柄。

如果此参数指定了现有的I / O完成端口,则该函数将其与FileHandle参数指定的句柄相关联。如果成功,该函数将返回现有I / O完成端口的句柄;它不会创建新的I / O完成端口。

如果此参数为NULL,则该函数将创建一个新的I / O完成端口,并且如果FileHandle参数有效,则将其与新的I / O完成端口关联。否则,不会发生文件句柄关联。如果成功,该函数将句柄返回到新的I / O完成端口。

CompletionKey [输入]

每个句柄用户定义的完成密钥,包含在指定文件句柄的每个I / O完成数据包中。有关更多信息,请参见“备注”部分。

NumberOfConcurrentThreads [输入]

操作系统可以允许同时处理I / O完成端口的I / O完成数据包的最大线程数。如果ExistingCompletionPort参数不为NULL,则忽略此参数。

如果此参数为零,则系统允许的并发运行线程数与系统中的处理器数量一样。

返回值
如果函数成功,则返回值是I / O完成端口的句柄:

如果ExistingCompletionPort参数为NULL,则返回值为新句柄。

如果ExistingCompletionPort参数是有效的I / O完成端口句柄,则返回值就是该句柄。

如果FileHandle参数是有效的句柄,则该文件句柄现在与返回的I / O完成端口关联。

如果函数失败,则返回值为NULL。若要获取扩展的错误信息,请调用GetLastError函数。

备注
可以指示I / O系统向排队的I / O完成端口发送I / O完成通知包。该CreateIoCompletionPort函数提供了此功能。

I / O完成端口及其句柄与创建它的进程相关联,并且不能在进程之间共享。但是,在同一进程中的线程之间可以共享一个句柄。

CreateIoCompletionPort可以在三种不同的模式下使用:

仅创建一个I / O完成端口,而不将其与文件句柄关联。
将现有的I / O完成端口与文件句柄相关联。
在一个调用中执行创建和关联。
要创建不关联的I / O完成端口,请将FileHandle参数设置为INVALID_HANDLE_VALUE,将ExistingCompletionPort参数设置为NULL,并将CompletionKey参数设置为零(在这种情况下将被忽略)。对于新的I / O完成端口,将NumberOfConcurrentThreads参数设置为所需的并发值,对于默认值(系统中的处理器数量),请将其设置为零。

在FileHandle参数中传递的句柄可以是任何支持重叠I / O的句柄。最常见的是,这是由CreateFile函数使用FILE_FLAG_OVERLAPPED标志打开的句柄(例如,文件,邮件插槽和管道)。由其他功能(例如套接字)创建的对象也可以与I / O完成端口关联。有关使用套接字的示例,请参见AcceptEx。一个句柄只能与一个I / O完成端口相关联,并且在建立关联之后,该句柄将一直与该I / O完成端口相关联,直到关闭它为止。

有关I / O完成端口理论,用法和相关功能的更多信息,请参见I / O完成端口。

通过使用ExistingCompletionPort参数中的相同I / O完成端口句柄和FileHandle参数中的不同文件句柄多次调用CreateIoCompletionPort多次,可以将多个文件句柄与单个I / O完成端口关联。

使用CompletionKey参数可帮助您的应用程序跟踪已完成的I / O操作。CreateIoCompletionPort不会使用此值进行功能控制;而是在与I / O完成端口关联时将其附加到FileHandle参数中指定的文件句柄。对于每个文件句柄,此完成密钥应该是唯一的,并且在整个内部完成排队过程中,它会伴随文件句柄。当完成数据包到达时,它在GetQueuedCompletionStatus函数调用中返回。该CompletionKey参数也使用PostQueuedCompletionStatus功能排队自己的专用完成包。

将打开句柄的实例与I / O完成端口关联后,由于这些函数具有其自己的异步I / O机制,因此无法在ReadFileEx或WriteFileEx函数中使用它。

最好不要通过句柄继承或对DuplicateHandle函数的调用来共享与I / O完成端口关联的文件句柄。使用此类重复句柄执行的操作将生成完成通知。建议仔细考虑。

I / O完成端口句柄以及与该特定I / O完成端口关联的每个文件句柄都称为对I / O完成端口的引用。没有更多引用时,将释放I / O完成端口。因此,必须正确关闭所有这些句柄才能释放I / O完成端口及其关联的系统资源。满足这些条件后,通过调用CloseHandle函数关闭I / O完成端口句柄。

在Windows 8和Windows Server 2012中,以下技术支持此功能。

#define WIN32_LEAN_AND_MEAN #define _WINSOCK_DEPRECATED_NO_WARNINGS #include <winsock2.h> #include <windows.h> #include <iostream> #include <iomanip> #include <sstream> #include <string> #include <fstream> #include <unordered_map> #include <algorithm> #include <cstring> #include <atomic> #include <thread> #include <chrono> #include <vector> #include <queue> #include <mutex> #include <condition_variable> #pragma comment(lib, "ws2_32.lib") #pragma comment(lib, "mswsock.lib") // 用于AcceptEx等异步操作 using namespace std; // 常量定义 constexpr DWORD CLIENT_SUB_ADDRESS = 0xAED9F0; constexpr DWORD CRAG_CONNECTION_INSTANCE_R_ADDRESS = 0xAEDE00; constexpr DWORD RECV_PTR_ADDRESS = 0x1424E18; constexpr int RING_BUFFER_SIZE = 64 * 1024; // 64KB环形缓冲区 constexpr int PACKET_POOL_SIZE = 1024; // 预分配1024个封包对象 constexpr int MAX_PACKET_SIZE = 8192; // 最大封包大小8KB constexpr DWORD TIMEOUT = 600000; // 10分钟超时 constexpr DWORD RECONNECT_INTERVAL = 3000; // 3秒重连间隔 constexpr DWORD PING_INTERVAL = 5000; // 5秒Ping间隔 constexpr DWORD SLEEP_TIME = 5; // 5ms休眠 constexpr DWORD HOOK_DELAY = 3000; // 3秒延迟应用Hook constexpr int WORKER_THREAD_COUNT = 4; // 工作线程数量 constexpr int MAX_ASYNC_OPS = 100; // 最大异步操作数量 enum e_PacketType { RECEIVED = 0, SENDED = 1 }; // 原子类型定义 using atomic_socket = atomic<SOCKET>; using atomic_bool = atomic<bool>; using atomic_dword = atomic<DWORD>; // 前向声明 typedef int(__thiscall* SendToClientFunc)(void* CragConnection, size_t size, char* buffer); typedef void* (__stdcall* originalInstanceR)(void); // 异步操作上下文 struct AsyncOperationContext { OVERLAPPED overlapped; SOCKET socket; WSABUF wsaBuf; char buffer[MAX_PACKET_SIZE]; DWORD bytesTransferred; DWORD flags; atomic_bool inUse; AsyncOperationContext() : socket(INVALID_SOCKET), bytesTransferred(0), flags(0) { ZeroMemory(&overlapped, sizeof(OVERLAPPED)); ZeroMemory(buffer, MAX_PACKET_SIZE); inUse.store(false, memory_order_relaxed); } void reset() { ZeroMemory(&overlapped, sizeof(OVERLAPPED)); bytesTransferred = 0; flags = 0; inUse.store(false, memory_order_relaxed); } }; // 线程安全的队列 template<typename T> class ThreadSafeQueue { private: queue<T> queue_; mutable mutex mutex_; condition_variable cond_; public: void push(T value) { lock_guard<mutex> lock(mutex_); queue_.push(move(value)); cond_.notify_one(); } bool try_pop(T& value) { lock_guard<mutex> lock(mutex_); if (queue_.empty()) { return false; } value = move(queue_.front()); queue_.pop(); return true; } bool empty() const { lock_guard<mutex> lock(mutex_); return queue_.empty(); } size_t size() const { lock_guard<mutex> lock(mutex_); return queue_.size(); } }; // 极简环形缓冲区 class SimpleRingBuffer { private: char* buffer; atomic<uint32_t> read_pos; atomic<uint32_t> write_pos; uint32_t size_mask; public: SimpleRingBuffer(uint32_t size) { // 确保大小为2的幂 uint32_t actual_size = 1; while (actual_size < size) actual_size <<= 1; buffer = new char[actual_size]; size_mask = actual_size - 1; read_pos.store(0, memory_order_relaxed); write_pos.store(0, memory_order_relaxed); } ~SimpleRingBuffer() { delete[] buffer; } uint32_t available_read() const { return write_pos.load(memory_order_acquire) - read_pos.load(memory_order_acquire); } uint32_t available_write() const { return size_mask + 1 - (write_pos.load(memory_order_acquire) - read_pos.load(memory_order_acquire)); } bool push(const char* data, uint32_t len) { uint32_t wp = write_pos.load(memory_order_acquire); uint32_t rp = read_pos.load(memory_order_acquire); uint32_t available = size_mask + 1 - (wp - rp); if (available < len) return false; uint32_t index = wp & size_mask; uint32_t first_chunk = min(len, size_mask + 1 - index); memcpy(buffer + index, data, first_chunk); if (first_chunk < len) { memcpy(buffer, data + first_chunk, len - first_chunk); } write_pos.store(wp + len, memory_order_release); return true; } uint32_t pop(char* dest, uint32_t len) { uint32_t rp = read_pos.load(memory_order_acquire); uint32_t wp = write_pos.load(memory_order_acquire); uint32_t available = wp - rp; if (available == 0) return 0; uint32_t to_read = min(len, available); uint32_t index = rp & size_mask; uint32_t first_chunk = min(to_read, size_mask + 1 - index); memcpy(dest, buffer + index, first_chunk); if (first_chunk < to_read) { memcpy(dest + first_chunk, buffer, to_read - first_chunk); } read_pos.store(rp + to_read, memory_order_release); return to_read; } void clear() { read_pos.store(0, memory_order_relaxed); write_pos.store(0, memory_order_relaxed); } }; // 极简内存池 class SimplePacketPool { private: struct PacketNode { char data[MAX_PACKET_SIZE]; uint16_t size; atomic<PacketNode*> next; }; PacketNode* nodes; atomic<PacketNode*> free_head; public: SimplePacketPool(size_t count) { nodes = new PacketNode[count]; // 构建链表 for (size_t i = 0; i < count - 1; ++i) { nodes[i].next.store(&nodes[i + 1], memory_order_relaxed); } nodes[count - 1].next.store(nullptr, memory_order_relaxed); free_head.store(nodes, memory_order_relaxed); } ~SimplePacketPool() { delete[] nodes; } PacketNode* acquire() { PacketNode* current_head = free_head.load(memory_order_acquire); while (current_head) { if (free_head.compare_exchange_weak(current_head, current_head->next.load(memory_order_acquire), memory_order_acq_rel, memory_order_acquire)) { return current_head; } } return nullptr; } void release(PacketNode* node) { if (!node) return; PacketNode* current_head = free_head.load(memory_order_acquire); node->next.store(current_head, memory_order_relaxed); while (!free_head.compare_exchange_weak(current_head, node, memory_order_acq_rel, memory_order_acquire)) { node->next.store(current_head, memory_order_relaxed); } } }; // 全局变量 atomic_socket koreClient(INVALID_SOCKET); atomic_socket roServer(INVALID_SOCKET); atomic_bool koreClientIsAlive(false); atomic_bool keepMainThread(true); atomic_bool imalive(false); atomic_bool hook_applied(false); atomic_bool hook_delayed(false); SimpleRingBuffer sendBuffer(RING_BUFFER_SIZE); SimplePacketPool packetPool(PACKET_POOL_SIZE); string koreServerIP; DWORD koreServerPort; bool allowMultiClient = false; // Hook相关 typedef int (WINAPI* recv_func_t)(SOCKET s, char* buf, int len, int flags); recv_func_t original_recv = nullptr; // 异步I/O相关 HANDLE iocpHandle = NULL; vector<AsyncOperationContext*> asyncContexts; ThreadSafeQueue<AsyncOperationContext*> freeContexts; mutex contextMutex; // 工作线程池 vector<thread> workerThreads; atomic_bool workersRunning(false); // 函数声明 void AllocateConsole(); void debug(const char* msg); bool CreateDefaultConfig(const std::string& filename); bool LoadConfig(const std::string& filename); bool ApplyHook(); void RemoveHook(); bool isConnected(SOCKET s); SOCKET createSocket(const std::string& ip, int port); DWORD GetUserPort(); void init(); void finish(); // 异步I/O函数声明 bool InitializeAsyncIO(); void CleanupAsyncIO(); AsyncOperationContext* GetAsyncContext(); void ReturnAsyncContext(AsyncOperationContext* context); bool PostAsyncRecv(SOCKET socket); void WorkerThreadProc(); bool InitializeWorkerThreads(); void CleanupWorkerThreads(); // 优化函数声明 SOCKET createOptimizedSocket(const std::string& ip, int port); void optimizedSendToKore(const char* data, uint16_t len, e_PacketType type); DWORD WINAPI highPerformancePacketProcessor(LPVOID lpParam); DWORD WINAPI koreConnectionMainOptimized(LPVOID lpParam); bool ApplyHookOptimized(); void initOptimized(); void finishOptimized(); void DelayedHookApplication(); // IOCP优化器 class IOCPOptimizer { private: HANDLE iocp_handle; public: IOCPOptimizer() : iocp_handle(NULL) {} bool initialize() { iocp_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0); return iocp_handle != NULL; } bool associateSocket(SOCKET socket) { return CreateIoCompletionPort((HANDLE)socket, iocp_handle, 0, 0) != NULL; } HANDLE getHandle() { return iocp_handle; } ~IOCPOptimizer() { if (iocp_handle) { CloseHandle(iocp_handle); } } }; IOCPOptimizer iocp_optimizer; // 异步I/O初始化 bool InitializeAsyncIO() { // 创建IOCP句柄 iocpHandle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, WORKER_THREAD_COUNT); if (iocpHandle == NULL) { cout << "[错误] 创建IOCP句柄失败: " << GetLastError() << endl; return false; } // 预分配异步操作上下文 for (int i = 0; i < MAX_ASYNC_OPS; ++i) { AsyncOperationContext* context = new AsyncOperationContext(); asyncContexts.push_back(context); freeContexts.push(context); } cout << "[成功] 异步I/O初始化完成,预分配 " << MAX_ASYNC_OPS << " 个上下文" << endl; return true; } // 清理异步I/O资源 void CleanupAsyncIO() { if (iocpHandle) { CloseHandle(iocpHandle); iocpHandle = NULL; } // 清理异步上下文 for (auto context : asyncContexts) { delete context; } asyncContexts.clear(); // 清空空闲队列 while (!freeContexts.empty()) { AsyncOperationContext* context = nullptr; freeContexts.try_pop(context); } } // 获取异步操作上下文 AsyncOperationContext* GetAsyncContext() { AsyncOperationContext* context = nullptr; if (freeContexts.try_pop(context)) { context->inUse.store(true, memory_order_relaxed); return context; } // 如果没有空闲上下文,动态创建一个(应该很少发生) lock_guard<mutex> lock(contextMutex); context = new AsyncOperationContext(); context->inUse.store(true, memory_order_relaxed); asyncContexts.push_back(context); cout << "[警告] 动态创建异步上下文,当前总数: " << asyncContexts.size() << endl; return context; } // 归还异步操作上下文 void ReturnAsyncContext(AsyncOperationContext* context) { if (context) { context->reset(); freeContexts.push(context); } } // 提交异步接收操作 bool PostAsyncRecv(SOCKET socket) { AsyncOperationContext* context = GetAsyncContext(); if (!context) { cout << "[错误] 无法获取异步上下文" << endl; return false; } context->socket = socket; context->wsaBuf.buf = context->buffer; context->wsaBuf.len = MAX_PACKET_SIZE; context->bytesTransferred = 0; context->flags = 0; DWORD bytesReceived = 0; // 使用WSARecv进行异步接收 int result = WSARecv(socket, &context->wsaBuf, 1, &bytesReceived, &context->flags, &context->overlapped, NULL); if (result == SOCKET_ERROR) { int error = WSAGetLastError(); if (error != WSA_IO_PENDING) { cout << "[错误] WSARecv失败: " << error << endl; ReturnAsyncContext(context); return false; } } return true; } // 工作线程处理函数 void WorkerThreadProc() { while (workersRunning.load(memory_order_acquire)) { DWORD bytesTransferred = 0; ULONG_PTR completionKey = 0; LPOVERLAPPED overlapped = nullptr; // 等待IOCP完成事件 BOOL success = GetQueuedCompletionStatus(iocpHandle, &bytesTransferred, &completionKey, &overlapped, INFINITE); if (!workersRunning.load(memory_order_acquire)) { break; } if (!overlapped) { // 收到退出信号 continue; } // 获取异步上下文 AsyncOperationContext* context = CONTAINING_RECORD(overlapped, AsyncOperationContext, overlapped); if (!success) { DWORD error = GetLastError(); if (error != WAIT_TIMEOUT) { cout << "[错误] IOCP操作失败: " << error << endl; // 处理连接断开 if (context->socket == koreClient.load(memory_order_acquire)) { koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); } } ReturnAsyncContext(context); continue; } // 处理接收到的数据 if (bytesTransferred > 0) { // 处理数据包逻辑 char* data = context->buffer; int remaining = bytesTransferred; while (remaining >= 3) { char packet_type = data[0]; uint16_t packet_len = *reinterpret_cast<uint16_t*>(data + 1); if (remaining < 3 + packet_len) break; if (packet_type == 'S' && packet_len > 0) { // 发送到RO客户端 auto* sendFunc = reinterpret_cast<SendToClientFunc>(CLIENT_SUB_ADDRESS); auto* instanceR = reinterpret_cast<originalInstanceR>(CRAG_CONNECTION_INSTANCE_R_ADDRESS); if (sendFunc && instanceR) { void* instance = instanceR(); if (instance) { sendFunc(instance, packet_len, data + 3); } } } int packet_total_size = 3 + packet_len; data += packet_total_size; remaining -= packet_total_size; } // 继续提交异步接收 if (context->socket != INVALID_SOCKET) { PostAsyncRecv(context->socket); } } else { // 连接关闭 if (context->socket == koreClient.load(memory_order_acquire)) { koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); } ReturnAsyncContext(context); } } } // 初始化工作线程池 bool InitializeWorkerThreads() { workersRunning.store(true, memory_order_release); for (int i = 0; i < WORKER_THREAD_COUNT; ++i) { workerThreads.emplace_back(WorkerThreadProc); } cout << "[成功] 启动 " << WORKER_THREAD_COUNT << " 个工作线程" << endl; return true; } // 清理工作线程池 void CleanupWorkerThreads() { workersRunning.store(false, memory_order_release); // 向所有线程发送退出信号 for (size_t i = 0; i < workerThreads.size(); ++i) { PostQueuedCompletionStatus(iocpHandle, 0, 0, NULL); } // 等待线程退出 for (auto& thread : workerThreads) { if (thread.joinable()) { thread.join(); } } workerThreads.clear(); cout << "[信息] 工作线程池已清理" << endl; } // 优化的recv钩子函数 int WINAPI hooked_recv(SOCKET s, char* buf, int len, int flags) { int result = original_recv(s, buf, len, flags); if (result > 0) { roServer.store(s, memory_order_release); // 使用内存池避免动态分配 auto packet_node = packetPool.acquire(); if (packet_node) { packet_node->size = static_cast<uint16_t>(result); memcpy(packet_node->data, buf, result); // 构建发送数据 char send_buf[3 + MAX_PACKET_SIZE]; send_buf[0] = 'R'; *reinterpret_cast<uint16_t*>(send_buf + 1) = packet_node->size; memcpy(send_buf + 3, packet_node->data, packet_node->size); // 非阻塞写入环形缓冲区 if (!sendBuffer.push(send_buf, 3 + packet_node->size)) { // 缓冲区满,直接发送到RO服务器(降级处理) SOCKET ro_sock = roServer.load(memory_order_acquire); if (ro_sock != INVALID_SOCKET) { send(ro_sock, buf, result, 0); } } packetPool.release(packet_node); } } return result; } // 控制台分配 void AllocateConsole() { AllocConsole(); freopen_s((FILE**)stdout, "CONOUT$", "w", stdout); freopen_s((FILE**)stderr, "CONOUT$", "w", stderr); freopen_s((FILE**)stdin, "CONIN$", "r", stdin); #ifdef UNICODE SetConsoleTitle(L"xKore优化版 - 调试控制台"); #else SetConsoleTitle("xKore优化版 - 调试控制台"); #endif } // 调试输出 void debug(const char* msg) { cout << "[调试] " << msg << endl; } // 创建默认配置 bool CreateDefaultConfig(const std::string& filename) { ofstream fout(filename); if (!fout.is_open()) { cout << "[错误] 无法创建配置文件: " << filename << endl; return false; } fout << "# xKore服务器配置\n"; fout << "koreServerIP=127.0.0.1\n"; fout << "koreServerPort=2350\n"; fout << "\n"; fout << "# 多客户端配置\n"; fout << "# 如果为true, 每次执行时在终端询问端口\n"; fout << "# 如果为false, 总是使用koreServerPort的默认端口\n"; fout << "allowMultiClient=true"; fout.close(); cout << "[成功] 默认配置文件已创建: " << filename << endl; return true; } // 加载配置 bool LoadConfig(const std::string& filename) { ifstream fin(filename); if (!fin.is_open()) { if (!CreateDefaultConfig(filename)) { return false; } cout << "\n*** 注意: 使用前请配置 '" << filename << "' 文件! ***" << endl; cout << "========================\n" << endl; fin.open(filename); if (!fin.is_open()) { cout << "[错误] 无法打开创建的配置文件: " << filename << endl; return false; } } string line; unordered_map<string, string> mapa; while (getline(fin, line)) { if (line.empty()) continue; if (line[0] == '#' || line[0] == ';') continue; size_t pos = line.find('='); if (pos == string::npos) continue; string chave = line.substr(0, pos); string valor = line.substr(pos + 1); while (!chave.empty() && isspace(chave.back())) chave.pop_back(); while (!valor.empty() && isspace(valor.front())) valor.erase(0, 1); while (!valor.empty() && isspace(valor.back())) valor.pop_back(); mapa[chave] = valor; } fin.close(); if (mapa.count("koreServerIP") == 0 || mapa.count("koreServerPort") == 0) { cout << "[错误] config_recv.txt中缺少必要的键。需要:\n" << " koreServerIP\n" << " koreServerPort\n"; return false; } try { koreServerIP = mapa.at("koreServerIP"); koreServerPort = static_cast<DWORD>(stoul(mapa.at("koreServerPort"), nullptr, 10)); if (mapa.count("allowMultiClient") > 0) { string allowMultiStr = mapa.at("allowMultiClient"); transform(allowMultiStr.begin(), allowMultiStr.end(), allowMultiStr.begin(), ::tolower); allowMultiClient = (allowMultiStr == "true" || allowMultiStr == "1" || allowMultiStr == "yes"); } } catch (exception& e) { cout << "[错误] 转换值时出现异常: " << e.what() << endl; return false; } cout << "[信息] 配置加载成功:\n\n" << " koreServerIP = " << koreServerIP << "\n" << " koreServerPort = " << koreServerPort << "\n" << " allowMultiClient = " << (allowMultiClient ? "true" : "false") << endl; return true; } // 应用Hook(优化版) bool ApplyHookOptimized() { if (original_recv != nullptr) { return true; // 已经hook } recv_func_t* recv_ptr = reinterpret_cast<recv_func_t*>(RECV_PTR_ADDRESS); original_recv = *recv_ptr; if (original_recv == nullptr) { cout << "错误: 原始recv指针为空!" << endl; return false; } *recv_ptr = hooked_recv; // 验证hook是否成功 if (*recv_ptr == hooked_recv) { hook_applied.store(true, memory_order_release); cout << "Hook应用成功!" << endl; return true; } return false; } // 延迟应用Hook函数 void DelayedHookApplication() { cout << "[信息] 等待3秒后应用Hook(避免强壳和NP检测)..." << endl; // 等待3秒 this_thread::sleep_for(chrono::milliseconds(HOOK_DELAY)); cout << "[信息] 开始应用Hook..." << endl; if (ApplyHookOptimized()) { cout << "[成功] 延迟Hook应用成功" << endl; hook_delayed.store(true, memory_order_release); } else { cout << "[错误] 延迟Hook应用失败" << endl; } } // 移除Hook void RemoveHook() { if (original_recv) { recv_func_t* recv_ptr = reinterpret_cast<recv_func_t*>(RECV_PTR_ADDRESS); *recv_ptr = original_recv; cout << "Hook已移除!" << endl; } } // 检查socket连接状态 bool isConnected(SOCKET s) { if (s == INVALID_SOCKET) return false; fd_set readfds; FD_ZERO(&readfds); FD_SET(s, &readfds); timeval timeout = { 0, 0 }; int result = select(0, &readfds, NULL, NULL, &timeout); if (result == SOCKET_ERROR) return false; return true; } // 创建优化socket SOCKET createOptimizedSocket(const std::string& ip, int port) { sockaddr_in addr; SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (sock == INVALID_SOCKET) { cout << "[错误] 创建socket失败: " << WSAGetLastError() << endl; return INVALID_SOCKET; } // 关键TCP优化参数 int nodelay = 1; if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char*)&nodelay, sizeof(nodelay)) == SOCKET_ERROR) { cout << "[警告] 设置TCP_NODELAY失败: " << WSAGetLastError() << endl; } // 设置发送缓冲区大小 int send_buf_size = 64 * 1024; setsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&send_buf_size, sizeof(send_buf_size)); // 设置接收缓冲区大小 int recv_buf_size = 64 * 1024; setsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&recv_buf_size, sizeof(recv_buf_size)); addr.sin_family = AF_INET; addr.sin_port = htons(static_cast<u_short>(port)); addr.sin_addr.s_addr = inet_addr(ip.c_str()); // 非阻塞连接 unsigned long mode = 1; ioctlsocket(sock, FIONBIO, &mode); int connect_result = connect(sock, (struct sockaddr*)&addr, sizeof(addr)); // 等待连接完成 fd_set writefds; FD_ZERO(&writefds); FD_SET(sock, &writefds); timeval timeout = { 3, 0 }; // 3秒超时 int select_result = select(0, NULL, &writefds, NULL, &timeout); if (select_result <= 0) { cout << "[错误] 连接超时或失败: " << WSAGetLastError() << endl; closesocket(sock); return INVALID_SOCKET; } // 检查socket错误 int error = 0; int error_len = sizeof(error); getsockopt(sock, SOL_SOCKET, SO_ERROR, (char*)&error, &error_len); if (error != 0) { cout << "[错误] 连接失败: " << error << endl; closesocket(sock); return INVALID_SOCKET; } // 恢复阻塞模式 mode = 0; ioctlsocket(sock, FIONBIO, &mode); // 关联到IOCP if (iocpHandle) { CreateIoCompletionPort((HANDLE)sock, iocpHandle, 0, 0); } return sock; } // 优化数据发送 void optimizedSendToKore(const char* data, uint16_t len, e_PacketType type) { if (!koreClientIsAlive.load(memory_order_acquire)) return; char header[3]; header[0] = (type == RECEIVED) ? 'R' : 'S'; *reinterpret_cast<uint16_t*>(header + 1) = len; // 先尝试写入header if (!sendBuffer.push(header, 3)) { return; // 缓冲区满,丢弃数据 } // 再写入数据 if (!sendBuffer.push(data, len)) { // 回滚header写入 char temp[3]; sendBuffer.pop(temp, 3); } } // 高性能封包处理线程 DWORD WINAPI highPerformancePacketProcessor(LPVOID lpParam) { char local_buf[4096]; atomic_dword last_send_time(GetTickCount()); atomic_dword last_ping_time(GetTickCount()); while (keepMainThread.load(memory_order_acquire)) { DWORD current_time = GetTickCount(); // 处理发送缓冲区 uint32_t available = sendBuffer.available_read(); if (available > 0) { SOCKET kore_sock = koreClient.load(memory_order_acquire); if (kore_sock != INVALID_SOCKET) { uint32_t bytes_read = sendBuffer.pop(local_buf, min(available, sizeof(local_buf))); if (bytes_read > 0) { int sent = send(kore_sock, local_buf, bytes_read, 0); if (sent == SOCKET_ERROR) { // 发送失败,可能连接已断开 koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); } else { last_send_time.store(current_time, memory_order_relaxed); } } } } // 定期Ping(保持连接活跃) if (current_time - last_ping_time.load(memory_order_relaxed) > PING_INTERVAL) { SOCKET kore_sock = koreClient.load(memory_order_acquire); if (kore_sock != INVALID_SOCKET) { char ping_packet[3] = { 'K', 0, 0 }; send(kore_sock, ping_packet, 3, 0); } last_ping_time.store(current_time, memory_order_relaxed); } // 智能休眠:有数据时忙等待,无数据时短暂休眠 if (available == 0) { Sleep(1); // 1ms休眠减少CPU占用 } } return 0; } // 主连接线程(优化版) DWORD WINAPI koreConnectionMainOptimized(LPVOID lpParam) { // 等待Hook应用完成 while (!hook_delayed.load(memory_order_acquire) && keepMainThread.load(memory_order_acquire)) { cout << "[信息] 等待Hook应用完成..." << endl; Sleep(500); } if (!hook_applied.load(memory_order_acquire)) { cout << "[错误] Hook未应用,连接线程退出" << endl; return 1; } // 创建专用的封包处理线程 HANDLE packet_thread = CreateThread(NULL, 0, highPerformancePacketProcessor, NULL, CREATE_SUSPENDED, NULL); if (!packet_thread) { cout << "[错误] 创建封包处理线程失败: " << GetLastError() << endl; return 1; } // 设置线程优先级 SetThreadPriority(packet_thread, THREAD_PRIORITY_ABOVE_NORMAL); SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL); // 禁用线程库通知减少开销 DisableThreadLibraryCalls(GetModuleHandle(NULL)); // 启动封包处理线程 ResumeThread(packet_thread); char recv_buf[8192]; atomic_dword last_connect_attempt(0); atomic_dword last_activity_time(GetTickCount()); cout << "[信息] xKore连接线程已启动" << endl; while (keepMainThread.load(memory_order_acquire)) { DWORD current_time = GetTickCount(); SOCKET current_kore_client = koreClient.load(memory_order_acquire); // 连接管理 if (current_kore_client == INVALID_SOCKET || !isConnected(current_kore_client)) { if (current_time - last_connect_attempt.load(memory_order_relaxed) > RECONNECT_INTERVAL) { if (current_kore_client != INVALID_SOCKET) { shutdown(current_kore_client, SD_BOTH); closesocket(current_kore_client); } SOCKET new_socket = createOptimizedSocket(koreServerIP, koreServerPort); if (new_socket != INVALID_SOCKET) { koreClient.store(new_socket, memory_order_release); koreClientIsAlive.store(true, memory_order_release); imalive.store(true, memory_order_release); last_activity_time.store(current_time, memory_order_relaxed); // 提交异步接收操作 if (iocpHandle) { PostAsyncRecv(new_socket); } cout << "[成功] 已连接到xKore服务器 " << koreServerIP << ":" << koreServerPort << endl; } else { koreClientIsAlive.store(false, memory_order_release); imalive.store(false, memory_order_release); cout << "[错误] 连接xKore服务器失败" << endl; } last_connect_attempt.store(current_time, memory_order_relaxed); } Sleep(100); // 连接失败时短暂休眠 continue; } // 检查超时 if (current_time - last_activity_time.load(memory_order_relaxed) > TIMEOUT) { cout << "[警告] 连接超时,重新连接..." << endl; koreClient.store(INVALID_SOCKET, memory_order_release); continue; } // 如果没有使用异步I/O,则使用传统的recv if (!iocpHandle) { int bytes_received = recv(current_kore_client, recv_buf, sizeof(recv_buf), 0); if (bytes_received > 0) { last_activity_time.store(current_time, memory_order_relaxed); // 处理接收到的封包 const char* data_ptr = recv_buf; int remaining = bytes_received; while (remaining >= 3) { char packet_type = data_ptr[0]; uint16_t packet_len = *reinterpret_cast<const uint16_t*>(data_ptr + 1); if (remaining < 3 + packet_len) break; // 数据不完整 if (packet_type == 'S' && packet_len > 0) { // 发送到RO客户端 auto* sendFunc = reinterpret_cast<SendToClientFunc>(CLIENT_SUB_ADDRESS); auto* instanceR = reinterpret_cast<originalInstanceR>(CRAG_CONNECTION_INSTANCE_R_ADDRESS); if (sendFunc && instanceR) { void* instance = instanceR(); if (instance) { sendFunc(instance, packet_len, const_cast<char*>(data_ptr + 3)); } } } int packet_total_size = 3 + packet_len; data_ptr += packet_total_size; remaining -= packet_total_size; } } else if (bytes_received == 0) { // 连接关闭 cout << "[信息] xKore服务器断开连接" << endl; shutdown(current_kore_client, SD_BOTH); closesocket(current_kore_client); koreClient.store(INVALID_SOCKET, memory_order_release); koreClientIsAlive.store(false, memory_order_release); imalive.store(false, memory_order_release); } else if (bytes_received == SOCKET_ERROR) { int error = WSAGetLastError(); if (error != WSAEWOULDBLOCK) { cout << "[错误] 接收数据失败: " << error << endl; koreClient.store(INVALID_SOCKET, memory_order_release); } } } // 轻微休眠避免过高CPU占用 Sleep(SLEEP_TIME); } // 清理线程 keepMainThread.store(false, memory_order_release); WaitForSingleObject(packet_thread, 5000); CloseHandle(packet_thread); cout << "[信息] xKore连接线程已退出" << endl; return 0; } // 获取用户端口(多客户端模式) DWORD GetUserPort() { char input[256]; cout << "\n[多客户端模式]" << endl; cout << "请输入xKore服务器端口(默认: " << koreServerPort << "): "; if (fgets(input, sizeof(input), stdin)) { input[strcspn(input, "\r\n")] = 0; if (strlen(input) == 0) { cout << "使用默认端口: " << koreServerPort << endl; return koreServerPort; } int inputPort = atoi(input); if (inputPort > 0 && inputPort <= 65535) { cout << "使用自定义端口: " << inputPort << endl; return static_cast<DWORD>(inputPort); } else { cout << "无效端口! 使用默认端口: " << koreServerPort << endl; return koreServerPort; } } cout << "读取错误! 使用默认端口: " << koreServerPort << endl; return koreServerPort; } // 初始化函数 void initOptimized() { AllocateConsole(); cout << "=== xKore优化版 ===" << endl; cout << "架构: x86 (32位)" << endl; cout << "优化: 原子操作 + 内存池 + 环形缓冲区 + 异步I/O" << endl; cout << "特性: 3秒延迟Hook(避免强壳检测)" << endl; // 初始化Winsock WSADATA wsaData; if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { cout << "[错误] Winsock初始化失败" << endl; return; } // 加载配置 if (!LoadConfig("config_recv.txt")) { cout << "[致命] 加载配置文件失败" << endl; keepMainThread.store(false, memory_order_release); return; } // 多客户端模式 if (allowMultiClient) { koreServerPort = GetUserPort(); } // 初始化异步I/O系统 if (!InitializeAsyncIO()) { cout << "[警告] 异步I/O初始化失败,使用传统模式" << endl; } else { // 初始化工作线程池 if (!InitializeWorkerThreads()) { cout << "[警告] 工作线程池初始化失败,使用传统模式" << endl; CleanupAsyncIO(); } } // 创建延迟Hook应用线程 HANDLE hook_thread = CreateThread(NULL, 0, [](LPVOID) -> DWORD { DelayedHookApplication(); return 0; }, NULL, 0, NULL); if (hook_thread) { cout << "[信息] 延迟Hook线程已启动" << endl; CloseHandle(hook_thread); // 不需要保持句柄 } else { cout << "[错误] 创建延迟Hook线程失败: " << GetLastError() << endl; // 直接应用Hook作为备选方案 cout << "[信息] 尝试直接应用Hook..." << endl; ApplyHookOptimized(); } // 创建优化版主线程 HANDLE hThread = CreateThread(NULL, 0, koreConnectionMainOptimized, NULL, 0, NULL); if (hThread) { cout << "[成功] xKore主线程已启动" << endl; CloseHandle(hThread); // 不需要保持句柄 } else { cout << "[错误] 创建主线程失败: " << GetLastError() << endl; keepMainThread.store(false, memory_order_release); } cout << "====================\n" << endl; } // 清理函数 void finishOptimized() { cout << "[信息] 开始清理资源..." << endl; keepMainThread.store(false, memory_order_release); // 等待线程退出 Sleep(100); // 清理工作线程池和异步I/O CleanupWorkerThreads(); CleanupAsyncIO(); // 关闭socket连接 SOCKET sock = koreClient.exchange(INVALID_SOCKET, memory_order_acq_rel); if (sock != INVALID_SOCKET) { shutdown(sock, SD_BOTH); closesocket(sock); } sock = roServer.exchange(INVALID_SOCKET, memory_order_acq_rel); if (sock != INVALID_SOCKET) { closesocket(sock); } // 移除hook if (original_recv) { RemoveHook(); } // 清理Winsock WSACleanup(); cout << "[信息] 资源清理完成" << endl; } // DLL主入口 BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) { switch (ul_reason_for_call) { case DLL_PROCESS_ATTACH: // 禁用线程通知以减少开销 DisableThreadLibraryCalls(hModule); initOptimized(); break; case DLL_PROCESS_DETACH: finishOptimized(); break; case DLL_THREAD_ATTACH: case DLL_THREAD_DETACH: break; } return TRUE; }针对 RO 的1 对 1 单 IP 连接、高频小封包场景,IOCP 的 “恰到好处” 核心是:聚焦 “单连接下的高频 IO 效率”,砍掉多连接场景的冗余设计,用最小的资源开销解决 “卡顿、丢包” 问题,避免为 “用而用” 的过度优化。具体需在 6 个关键环节做到精准控制,既保留 IOCP 的核心优势,又不引入不必要的复杂度: 一、完成端口(IOCP)初始化:极简配置,不浪费内核资源 单连接场景下,IOCP 无需配置多连接的 “高并发参数”,核心是 “轻量化创建 + 绑定单 Socket”,避免内核资源闲置: 并发线程数设为 1,而非 CPU 核心数CreateIoCompletionPort 的第 4 个参数(NumberOfConcurrentThreads)控制允许同时处理 IO 事件的线程数。多连接场景会设为 CPU 核心数(如 4 核设 4),但单连接下 IO 事件是 “串行触发”(同一时间仅 1 个小封包待处理),设为1即可 —— 多线程反而会导致 “线程切换开销”(比如 2 个线程抢 1 个 IO 事件,浪费 CPU)。文档中IOCPOptimizer::initialize()用了默认的0(等于 CPU 核心数),可优化为1,更贴合单连接: cpp 运行 iocp_handle = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 1); // 最后一个参数设为1 仅关联 1 个目标 Socket,不做批量绑定单连接场景下,仅需将 RO 客户端与服务器的 Socket(或 xKore 代理的 Socket)关联到 IOCP,无需设计 “批量 Socket 绑定逻辑”(如循环绑定多个连接)。文档中associateSocket()单次绑定 1 个 Socket 的逻辑已适配,无需额外扩展。 二、线程池设计:1 个工作线程足够,拒绝 “多线程冗余” IOCP 的线程池是 “事件消费者”,单连接下高频小封包的 IO 事件是 “连续且串行” 的,1 个工作线程即可高效处理,多线程反而会引入 “锁竞争”(如抢读环形缓冲区),属于过度优化: 固定 1 个 IO 工作线程,不动态增减无需设计 “根据 IO 压力动态创建 / 销毁线程” 的逻辑(多连接场景才需要),直接创建 1 个常驻线程处理 IO 事件即可。比如文档中的highPerformancePacketProcessor线程,可固定为 1 个,无需用线程池库(如CreateThreadPool)—— 代码中SetThreadPriority设为THREAD_PRIORITY_ABOVE_NORMAL是合理的(保证 IO 处理优先级高于普通逻辑,避免小封包延迟),但无需多线程。 线程与 IO 事件 “一对一绑定”,避免线程切换单线程处理所有 IO 事件(读 / 写 / 错误),无需拆分 “读线程”“写线程”—— 拆分后会增加 “线程间通信开销”(如写线程通知读线程处理数据),反而降低效率。文档中 “1 个线程处理发送缓冲区 + Ping + 超时检测” 的逻辑已适配,无需修改。 三、IO 请求投递:预投递 + 小缓冲区,适配高频小封包 RO 的小封包(10~512 字节)若 “每次投递 1 个 IO 请求”,会导致系统调用(WSARecv/WSASend)频繁,反而增加开销。需用 “预投递 + 固定小缓冲区” 优化,平衡效率与资源: 预投递 1 个读请求,而非多次投递单连接下,Socket 接收缓冲区的小封包是 “连续到达” 的,可预先投递 1 个WSARecv请求(挂起等待数据),数据到达后处理完再投递下 1 个 —— 避免 “每收到 1 个小封包就投递 1 次请求” 的高频系统调用。示例逻辑: cpp 运行 // 预投递读请求(初始化时执行1次) OVERLAPPED ov; memset(&ov, 0, sizeof(ov)); char recv_buf[512]; // 适配RO小封包,不用8192字节大缓冲区 WSARecv(sock, &wsabuf, 1, NULL, &flags, &ov, NULL); // 处理完成事件后,再次投递下1个请求 while (keepRunning) { GetQueuedCompletionStatus(iocp_handle, &bytesTransferred, &key, &ov, INFINITE); processSmallPacket(recv_buf, bytesTransferred); // 处理小封包 WSARecv(sock, &wsabuf, 1, NULL, &flags, &ov, NULL); // 再次预投递 } 这里缓冲区设为512 字节(RO 小封包最大通常不超过 512),比文档中recv_buf[8192]更节省内存,且避免 “大缓冲区空闲浪费”。 写请求 “批量合并”,减少 WSASend 调用高频小封包发送时,若每次调用WSASend发送 1 个小封包(如 10 字节),系统调用开销占比极高。可结合文档中的环形缓冲区(sendBuffer) ,积累多个小封包(如累计到 1KB 或等待 1ms)后,一次性调用WSASend发送 —— 但需注意 “延迟平衡”(累计时间不超过 1ms,避免 RO 实时交互卡顿)。文档中 “有数据就发送” 的逻辑可微调:增加 “最小累计字节数”(如 128 字节),减少系统调用次数,又不影响延迟。 四、缓冲区与内存管理:贴合小封包,避免 “大缓冲冗余” RO 的小封包不需要大缓冲区,过度分配会导致内存浪费;同时需避免动态内存分配(高频小封包易引发内存碎片),文档中的内存池已适配,需进一步贴合场景: Socket 缓冲区设为 64KB,不盲目调大SO_SNDBUF/SO_RCVBUF 的大小需适配小封包:设为 64KB 足够(RO 每秒数百个小封包,总流量仅几十 KB),设为 128KB 或更大反而会增加 “缓冲区数据拷贝开销”(内核到用户态)。文档中send_buf_size = 64 * 1024的配置已恰到好处,无需修改。 内存池单包大小设为 512 字节,而非 8KB文档中MAX_PACKET_SIZE = 8192(8KB)过大,RO 小封包最大仅 512 字节,可改为512,减少内存池的内存占用(1024 个包仅 512KB,原 8KB 需 8MB)。同时避免 “大缓冲区拆分小封包” 的逻辑,简化内存池管理。 五、错误处理与降级:简单可靠,不做复杂容错 单连接场景下,IO 错误类型少(如连接断开、超时),无需设计 “复杂的错误重试逻辑”(如多连接的 “故障转移”),做到 “快速检测 + 优雅降级” 即可: 仅处理关键错误,避免冗余判断重点处理 3 类错误:WSAECONNRESET(连接被重置)、WSAETIMEDOUT(超时)、ERROR_NETNAME_DELETED(连接关闭),其他错误直接触发 “重连逻辑”(如文档中的koreClient.store(INVALID_SOCKET))。无需遍历所有 WSA 错误码,减少判断开销。 IOCP 初始化失败时,降级为 “简化异步 IO”若 IOCP 创建失败(如老旧系统不支持),无需崩溃,可降级为 “WSAEventSelect”(比 select 高效,比 IOCP 简单),而非直接用 select。文档中 “IOCP 关联失败仅警告” 的逻辑可优化为降级逻辑,保证兼容性,又不引入过度容错。 六、避免 “为 IOCP 而加的冗余特性” 单连接场景下,多连接 IOCP 的常见特性(如 “连接池”“负载均衡”“多完成端口拆分”)均无需实现,属于典型的过度优化: 不做 “连接池”:单连接无需缓存多个 Socket,直接创建 / 关闭即可; 不做 “多完成端口”:1 个完成端口足够处理单连接,多完成端口会增加内核调度开销; 不做 “IO 事件优先级”:单连接下所有小封包优先级相同(如移动、技能封包无先后),无需设计事件优先级队列。 总结:IOCP “恰到好处” 的核心原则 针对 RO 1 对 1 单连接、高频小封包场景,IOCP 的优化需围绕 “最小资源开销解决核心问题”: 资源上:1 个完成端口 + 1 个工作线程 + 64KB Socket 缓冲区 + 512 字节内存池,不浪费内存与 CPU; 逻辑上:预投递 1 个读请求 + 批量合并写请求 + 简单错误处理,不引入多线程、多完成端口等冗余设计; 目标上:仅解决 “select 轮询开销”“小封包延迟”“缓冲区溢出丢包” 三大问题,不追求 “多连接扩展性”“极致并发” 等无关特性。 这种设计既保留了 IOCP “异步无轮询” 的核心优势(从根源解决卡顿、丢包),又避免了过度优化带来的复杂度与资源浪费,完全适配 RO 的单连接高频小封包场景。
最新发布
09-24
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值