Windows 异步IO和 完成端口(IOCP)
见过网上好多的完成端口和网络通信的文章,呵呵,这里就简单的说说文件异步IO和完成端口,这里仅仅说说读取操作。下面是一些总结,很少有人提及,认真的看过MSDN文档之后得出的,欢迎指正。
这里简单的附上一段异步代码:
#include <process.h>#include <Windows.h>VOID WINAPI rt( __in DWORD dwErrorCode, __in DWORD dwNumberOfBytesTransfered, __inout LPOVERLAPPED lpOverlapped){ printf("rt call back\n");}int _tmain(int argc, _TCHAR* argv[]){ OVERLAPPED *ol = new OVERLAPPED; memset(ol, 0, sizeof *ol); HANDLE file = CreateFile("ReadMe.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL); if(file == INVALID_HANDLE_VALUE) { goto mem_free1; } size_t buf_len = 1024; char *buf = new char[buf_len]; if(!buf) { goto mem_free1; } if(!ReadFileEx(file, buf, buf_len, ol, rt)) { goto mem_free; } SleepEx(INFINITE, TRUE);mem_free: delete []buf;mem_free1: delete ol; CloseHandle(file);return 0;}
对于ReadFile,主线程在触发异步操作之后,就需要有另外的线程来做辅助工作,可以使用event事件,这里主要介绍完成端口,没有多少好说的,也贴上代码吧:
#include <process.h>#include <windows.h>//创建一个IO完成端口HANDLE CreateNewCompletionPort(DWORD dwNumberOfConcurrentThreads){ return( CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, NULL, dwNumberOfConcurrentThreads));}//将设备与完成端口管理起来BOOL AssociateDeviceWithCompletionPort(HANDLE hCompletionPort, HANDLE hDevice, DWORD dwCompletionKey) { HANDLE h = CreateIoCompletionPort(hDevice, hCompletionPort, dwCompletionKey, 0); return (h == hCompletionPort);}void reader(void *in){ HANDLE port = (HANDLE)in; DWORD rcv_len = 0; ULONG_PTR my_key = 0; OVERLAPPED *ol1 = NULL; while(1) { if(!GetQueuedCompletionStatus(port, &rcv_len, &my_key, &ol1, INFINITE)) { int err = GetLastError(); continue; } else { _endthread(); } }}int _tmain(int argc, _TCHAR* argv[]){ int key = 12345; HANDLE port = CreateNewCompletionPort(4); if(!port) { int err = GetLastError(); return 0; } HANDLE file = CreateFile("ReadMe.txt", GENERIC_READ, 0, NULL, OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED , NULL); if(file == INVALID_HANDLE_VALUE) { CloseHandle(port); } OVERLAPPED *ol = new OVERLAPPED; memset(ol, 0, sizeof *ol); if(!AssociateDeviceWithCompletionPort(port, file, key)) { int err = GetLastError(); CloseHandle(port); CloseHandle(file); delete ol; return 0; } int buf_len = 1000; char *buf = new char[buf_len]; if(!buf) { CloseHandle(port); CloseHandle(file); delete ol; return 0; } HANDLE h_thread = (HANDLE)_beginthread(reader, 0, port); if(!ReadFile(file, buf, buf_len, NULL, ol)) { int err = GetLastError(); if(err != ERROR_IO_PENDING) { CloseHandle(port); CloseHandle(file); delete ol; WaitForSingleObject(h_thread, INFINITE); return 0; } } WaitForSingleObject(h_thread, INFINITE); CloseHandle(port); CloseHandle(file); delete ol; delete []buf; return 0;}