Windows下性能最好的I/O模型——完成端口
来源:互联网 发布:网络胜利组风车动漫 编辑:程序博客网 时间:2024/06/08 04:36
Windows下性能最好的I/O模型——完成端口
I/O模型——完成端口
设计目的:
常见的网络通信分为两种:同步和异步。
在同步通信中,每一次接受数据都会导致主线程的挂起,从而阻塞住了其他操作。为了解决这一问题,我们通常会采取同步通信+多线程的策略,即为每一个连入的Socket分配一个线程。然而随着连入的Socket的数量的增加,线程的数量也在增加,这样CPU则需要不停地进行线程的切换,因此难以成为高性能的服务器程序。
异步通信则可以把接收数据这一操作交给内核,即在内核接收数据的时候,主线程可以不用被阻塞并且继续执行其他操作,而一旦接收数据完成以后,再由内核通知主线程。而如何通知主线程是一个关键,不同的异步通信策略有着不同的通知方式。
在这样的情况下,完成端口这一I/O模型被提出,成为目前Windows下性能最好的I/O模型之一。
实现原理:
首先根据CPU数量开好线程,当有用户请求的时候,把这些请求加入一个特定的消息队列中,而事先开好的线程则会排队从这个消息队列中获取请求并作出处理。完成端口正是指这一消息队列.
基本流程:
主要的API:
- 创建完成端口
HANDLE iocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0 );
HANDLE WINAPI CreateIoCompletionPort( _in_ HANDLE FileHandle, // Socket的句柄,置为INVALID_HANDLE_VALUE表示创建一个没有和任何HANDLE有关系的完成端口 _in_opt HANDLE ExistingCompletionPort, // NULL表示新建一个完成端口 _in_ ULONG_PTR CompletionKey, // 完成键,创建完成端口时置为0 _in_ DWORD NumberOfConcurrentThreads // 完成端口并发线程的数量,置0表示有多少个CPU就开多少个线程);
- 创建监听Socket
初始化Socket库......listenSoc = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);...绑定端口,并监听...
- 将监听的Socket绑定到完成端口上,这里同样使用
HANDLE WINAPI CreateIoCompletionPort(...)
这一API.
CreateIoCompletionPort(listenSoc, iocp, CompKey, 0);
HANDLE WINAPI CreateIoCompletionPort( _in_ HANDLE FileHandle, // 监听Socket的句柄 _in_opt HANDLE ExistingCompletionPort, // 刚才创建的完成端口 _in_ ULONG_PTR CompletionKey, // 完成键,我们在绑定的同时为其分配一段内存空间,以存储与这一Socket相关的信息,当网络操作完成的时候,我们可以根据这段内存空间里面的信息分辨这是哪一个Socket _in_ DWORD NumberOfConcurrentThreads // 完成端口并发线程的数量,置0表示有多少个CPU就开多少个线程);
- 在监听端口上投递AcceptEX请求
AcceptEX与传统的Accept有三个主要不同点:
- AcceptEX采取异步方式,可以同时投递多个请求,而Accept采取阻塞的方式,依次只能处理一个请求。
- AcceptEX会事先准备好Socket,当用户请求连入的时候直接使用这一新的Socket,避免临时创建Socket。
- AcceptEX接受连入请求的同时,我们可以附加一些数据,这样我们就可以在接受用户连入的同时,接受来自用户的第一组数据。
BOOL AcceptEx ( SOCKET sListenSocket, // 监听Socket SOCKET sAcceptSocket, // 事先准备好给新用户的Socket PVOID lpOutputBuffer, // 接受缓冲区 DWORD dwReceiveDataLength, // 用于存放用户第一组数据的空间大小 DWORD dwLocalAddressLength, // 本地地址的空间大小 DWORD dwRemoteAddressLength, // 客户端地址的空间大小 LPDWORD lpdwBytesReceived, LPOVERLAPPED lpOverlapped // 重叠结构,每一个网络操作都会对应一个重叠结构,相当于网络操作的ID);
- 投递接受数据请求
int WSARecv( SOCKET s, // 接受数据的Socket LPWSABUF lpBuffers, // 接收缓冲区 DWORD dwBufferCount, // 置为1 LPDWORD lpNumberOfBytesRecvd, // 所接收到的字节数 LPDWORD lpFlags, // 置为0 LPWSAOVERLAPPED lpOverlapped, // 这个Socket对应的重叠结构 NULL);
- 解析AcceptEX接收到的数据
AcceptEX缓冲区里面保存着本地地址,客户端地址以及客户端发来的第一组数据,因此我们需要使用GetAcceptExSockAddrs()
来解析这些数据.
void GetAcceptExSockaddrs( _In_ PVOID lpOutputBuffer, // AcceptEX中的缓冲区 _In_ DWORD dwReceiveDataLength, // 用户第一组数据的空间大小 _In_ DWORD dwLocalAddressLength, // 本地地址的空间大小 _In_ DWORD dwRemoteAddressLength, // 客户端地址的空间大小 _Out_ LPSOCKADDR *LocalSockaddr, // 本地地址 _Out_ LPINT LocalSockaddrLength, // 实际本地地址的空间大小 _Out_ LPSOCKADDR *RemoteSockaddr, // 客户端地址 _Out_ LPINT RemoteSockaddrLength // 实际客户端地址的大小);
参考: 1. 完成端口(CompletionPort)详解 - 手把手教你玩转网络编程系列之三
2. Overlapped模型深入分析
阅读全文
0 0
- Windows下性能最好的I/O模型——完成端口
- Windows下性能最好的I/O模型——完成端口
- IOCP 完成端口 是性能最好的一种I/O模型
- Windows Socket I/O模型之 I/O完成端口
- 完成端口I/O模型
- 完成端口I/O模型
- I/O完成端口模型
- Windows I/O完成端口
- Windows I/O完成端口
- Windows I/O完成端口
- windows I/O完成端口
- Windows操作系统I/O模型—笔记4(完成端口(Completion Port)模型+线程池技术)
- 《Windows via C/C++》学习笔记 —— 设备I/O之“I/O完成端口”
- [网络]I/O完成端口模型
- 完成端口I/O模型编写心得!
- WinSock完成端口I/O模型
- Socket I/O模型之完成端口
- WinSock完成端口I/O模型
- C++ istream_iterator
- sql2008“备份集中的数据库备份与现有的xx数据库不同”解决方法
- c#设计模式-单例模式
- Android 广播(Broadcast Receiver)使用详解
- JS 教程
- Windows下性能最好的I/O模型——完成端口
- 今天你的服务器被"挖矿"了吗?
- 【面试题】剑指offer14--调整一组数据使得奇数位 位于偶数位的前面
- GDC2017: 《Lone Echo》中的VR动画
- jquery-multiselect取值、刷新页面保持选中、AJAX相关问题集合
- 用户登录后更换会话ID
- 【Python】Python数据分析基础技术03
- ViewPager切换动画
- Entity Framework Repository模式