windows的重叠IO模型

2019年5月29日

11:58

?
?

同一线程内部向多个目标传输(或冲多个目标接收)数据引起的IO重叠现象称为"重叠IO"。为了完成这项任务,调用IO的函数应立即返回,只有这样才能返送后续数据。

重叠IO收发数据最重要的前提条件就是异步IO。

在windows中重叠IO的重点并非IO本身,而是如何确认IO完成时的状态。因为不管输入还是输出,只要时非阻塞模式的,就要另外确认执行结果。确认执行结果前需要经过特殊的处理过程。

?
?

创建重叠IO套接字

#include <winsock2.h>

SOCKET WSASocket(int af, int type, int protocal, LPWSAPROTOCAL_INFO lpProtocolInfo, GROUP g, DWORD dwFlags);

->>成功时返回套接字句柄,失败时返回INVALID_SOCKET

?
?

af 协议族信息

type 套接字数据传输方式

protocol 套接字使用协议信息

lpProtocalInfo 包含创建的套接字信息的WSAPROTOCAL_INFO结构体变量地址值,不需要时传递NULL

g 为扩展函数二预约的参数,可以使用0

dwFlags 套接字属性信息

?
?

首先是创建重叠IO套接字,并且之后要使用特殊的重叠IO函数收发数据,并且在收发数据以后通过特殊方法确认收发数据的成功与否。如果需要还可以通过注册在IO完成以后执行指定的函数。

?
?

执行重叠IO的WSASend函数

#include <winsock2.h>

int WSASend(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,

LPDWORD lpNumberOfBytesSent, DWORD dwFlags,

LPWSAOVERLAPPED lpOverlapped,

LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

->>成功时返回0,失败时返回SOCKET_ERROR

?
?

s 套接字句柄,传递具有重叠IO属性的套接字句柄时,以重叠IO模型输出

lpBuffers WSABUF结构体变量数组的地址值,WSABUF中存有待传输的数据

dwBufferCount 第二个参数中数组的长度

lpNumberOfBytesSent 用于保存实际发送字节数的变量地址

dwFlags 用于更改数据传输特性

lpOverlapped WSAOVERLAPPED结构体变量的地址值,使用事件对象,用于确认完成数据传输

lpCompletionRoutine 传入Completion Routine函数的入口地址值,可以通过干函数确认是否完成数据传输

?
?

WSABUF结构体定义

typedef struct __WSABUF

{

u_long len; // 待传输数据的大小

char FAR * buf; // 缓冲地址值

}WSABUF, * LPWSABUF;

?
?

示例:

WSAEVENT event;

WSAOVERLAPPED overlapped;

WSABUF databuf;

char buf[BUF_SIZE] = {"待传输的数据"};

int recvBytes = 0;

event = WSACreateEvent();

memset(&overlapped, 0, sizeof(overlapped)); // 所有位初始化为0

overlapped.hEvent = event;

dataBuf.len = sizeof(buf);

dataBuf.buf = buf;

WSASend(hSocket, &dataBuf, 1, &recvBytes, 0, &overlapped, NULL);

?
?

WSAOVERLAPPEd 结构体定义如下

typedef struct _WSAOVERLAPPE

{

DWORD Internal;

DWORD InternalHigh;

DWORD Offset;

DWORD OffsetHigh;

WSAEVENT hEvent;

}WSAOVERLAPPED, * LPWSAOVERLAPPED;

Internal, InternalHigh为进行重叠IO时操作系统内部使用的成员,Offset, OffsetHigh同样具有特殊用途,实际只需要关注hEvent成员

?
?

如果向overlapped参数传递NUll,则套接字将以阻塞方式工作。同样如果利用WSASend函数向多个目标传输数据,则每个目标都需要具有独自的WSAOVERLAPPED结构体变量

?
?

还具有一种情况就是在WSASend调用结束立即返回的同时,数据也同时传输完成。在这个时候WSASend函数返回0,同时在recvBytes中填充发送的字节数。反之(数据没有传输完成),WSASend仍需传输数据时,将返回SOCKET_ERROR,并将WSA_IO_PENDING(尚未完成状态Pending)注册为错误代码(错误代码通过WSAGetLastError获得)。之后通过WSAGetOverlappedResult获取实际传输大小。

?
?

执行重叠IO的WSARecv函数

#include <winsock2.h>

int WSARecv(SOCKET s, LPWSABUF lpBuffers, DWORD dwBufferCount,

LPDWORD lpNumberOfBytesRecvd, LPDWORD lpFlags,

LPWSAOVERLAPPED lpOverlapped,

LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine);

->>成功时返回0,失败时返回SOCKET_ERROR

?
?

s 赋予重叠IO属性的套接字句柄

lpBuffers 用于保存接收数据的WSABUF结构体数组地址值

dwBufferCount 向第二个参数传递的数组的长度

lpNumberOfBytesRecvd 保存接收数据大小信息的地址值

lpFlags 用于设置或读取传输特性信息

lpOverlapped WSAOVERLAPPED结构体变量地址

lpCompletionRoutine Completion Routine函数地址

?
?

Gather/Scatter I/O是指将多个缓冲区中的数据积累到一定程度后一次型传输(Gather输出),将接收的数据分批保存(Scatter输入)。Linux下的writev&readv函数具有Gather/Scatter I/O功能,但是windows下并没有这些函数的定义。不过可以通过重叠IO中的WSASend和WSARecv函数获得类似的功能。他们的第二个参数和第三个参数中就可以判断出其具有Gather/Scatter I/O功能。

?
?

获得实际传输大小

#include <winsock2.h>

BOOL WSAGetOverlappedResult(SOCKET s, LPWSAOVERLAPPED lpOverlapped,

LPDWORD lpcbTreansfer, BOOL fWait, LPDWORD lpdwFlags);

->>成功时返回TRUE,失败时返回FALSE

?
?

s 重叠IO套接字

lpOverlapped WSAOVERLAPPED结构体变量地址

lpcbTransfer 用于保存实际传输字节数的变量地址

fWait 如果调用该函数时仍在进行IO,是否等待IO完成,TRUE等待,FALSE不等待(返回FALSE并跳出函数)。

lpdwFlags 用于获取附加信息(如OOB消息)。如果不需要,可以传递NULL

?
?

重叠IO的IO完成确认

重叠IO中有两种方法确认IO的完成并获取结果

  • 利用WSASend、WSARecv函数的第六个参数,基于事件对象
  • 利用WSASend、WSARecv函数的第七个参数,基于Completion Routine

?
?

使用前一种方法时需要注意:

  • 完成IO时,WSAOVERLAPPED结构体变量引用的事件对象将编程为signaled状态
  • 为了验证IO的完成和完成结构,需要调用WSAGetOverlappedResult函数

?
?

使用Completion Routine函数

可以通过WSARecv&WSASend函数的最后一个参数中指定的Completion Routine(以下简称CR)函数验证IO完成情况。

?
?

"注册CR"有如下含义:"Pending的IO完成以后调用此函数"

但是如果执行重要任务时突然调用Completion Routine,则有可能会破坏程序的正常执行流。因此操作系统通常都会预先定义规则:"只有请求I/O的线程处于alertalble wait状态时才能调用Completion Routine函数"

?
?

"alertable wait状态"时等待接收操作系统消息的线程状态,调用以下函数可以进入alertable wait状态

  • WaitForSingleObjectEx
  • WaitForMultipleObjectsEx
  • WSAWaitForMultipleEvents
  • SleepEx

?
?

第一,第二,第四个参数提供的功能与WaitForSingleObject,WaitForMultipleObjects,Sleep函数相同,只是额外增加了1个参数。如果该参数为TRUE,则相应线程进入alertable wait状态

第三个函数的最后一个参数设置为TRUE时,线程同样进入alertable wait状态。

?
?

启动IO任务后,执行完紧急任务时可以调用上述任意函数验证IO完成与否,此时操作系统知道线程进入alertable wait状态,如果有已经完成的IO。则调用相应的Completion Routine函数。调用以后上述函数将全部返回WAIT_IO_COMPLETION,并开始执行接下来的程序

?
?

Completion Routine函数原型

void CALLBACK CompletionROUTINE(DWORD dwError, DWORD cbTransferred,

LPWSAOVERLAPPED lpOverlapped, DWORD dwFlags);

?
?

参数一 中写入错误信息(正常结束时写入0)

参数二 写入实际收发的字节数

参数三 写入WSASend,WSARecv函数的参数lpOverlapped

dwFlags 写入调用IO函数时传入的特性信息或者0

?
?

?
?

??

原文地址:https://www.cnblogs.com/freesfu/p/10943508.html

时间: 2024-10-11 08:38:51

windows的重叠IO模型的相关文章

Windows五种IO模型性能分析和Linux五种IO模型性能分析

Windows五种IO模型性能分析和Linux五种IO模型性能分析 http://blog.csdn.net/jay900323/article/details/18141217 http://blog.csdn.net/jay900323/article/details/18140847 重叠I/O模型的另外几个优点在于,微软针对重叠I/O模型提供了一些特有的扩展函数.当使用重叠I/O模型时,可以选择使用不同的完成通知方式. 采用事件对象通知的重叠I/O模型是不可伸缩的,因为针对发出WSAWa

重叠IO 模型

1. 重叠模型的优点 2. 重叠模型的基本原理 3. 关于重叠模型的基础知识 4. 重叠模型的实现步骤 5. 多客户端情况的注意事项 一.重叠模型的优点   1.可以运行在支持Winsock2的所有Windows平台 ,而不像完成端口只是支持NT系统. 2.比起阻塞.select.WSAAsyncSelect以及WSAEventSelect等模型,重叠I/O(Overlapped   I/O)模型使应用程序能达到更佳的系统性能.    因为它和这4种模型不同的是,使用重叠模型的应用程序通知缓冲区

四.Windows I/O模型之重叠IO(overlapped)模型

1.适用于除Windows CE之外的各种Windows平台.在使用这个模型之前应该确保该系统安装了Winsock2.重叠模型的基本设计原理是使用一个重叠的数据结构,一次投递一个或多个Winsock I/O请求.在重叠模型中,收发数据使用WSA开头的函数. 2.WSA_FLAG_OVERLAPPED标志:要使用重叠模型.在创建套接字的时候,必须加上该标志.SOCKET s=WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);假如

重叠io操作

第一章 一. 重叠模型的优点 1. 可以运行在支持Winsock2的所有Windows平台 ,而不像完成端口只是支持NT系统. 2. 比起阻塞.select.WSAAsyncSelect以及WSAEventSelect等模型,重叠I/O(Overlapped I/O)模型使应用程序能达到更佳的系统性能. 因为它和这4种模型不同的是,使用重叠模型的应用程序通知缓冲区收发系统直接使用数据,也就是说,如果应用程序投递了一个10KB大小的缓冲区来接收数据,且数据已经到达套接字,则该数据将直接被拷贝到投递

Linux 的 Socket IO 模型

前言 之前有看到用很幽默的方式讲解Windows的socket IO模型,借用这个故事,讲解下linux的socket IO模型: 老陈有一个在外地工作的女儿,不能经常回来,老陈和她通过信件联系. 他们的信会被邮递员投递到他们小区门口的收发室里.这和Socket模型非常类似. 下面就以老陈接收信件为例讲解linux的 Socket I/O模型. 一.同步阻塞模型 老陈的女儿第一次去外地工作,送走她之后,老陈非常的挂心她安全到达没有:于是老陈什么也不干,一直在小区门口收发室里等着她女儿的报平安的信

Windows五个网络IO模型(服务器用)

1.选择select 2.异步选择WSAAsyncSelecct 3.事件选择WSAEventSelect  100-500客户端使用 4.重叠IO Verlapped IO 5.完成端口Completion Port(常配合线程池,内存池技术一起使用) 10000-20000客户端使用 ----------------- 客户端可以不用网络模型,直接用阻塞IO模型.

winsock的io模型(终极篇)

最近在看服务器框架的搭建,看了不少,都是零零碎碎的,觉得看的差不多了,可以写点最后的总结了,然后,竟然发现了这篇文章,总结做的特别好,肯定比我总结写要好多了,所以我也就不写了,直接转吧...... 套接字模式:锁定.非锁定套接字I/O模型:       select(选择)WSAAsyncSelect(异步选择)WSAEventSelect(事件选择)Overlapped I/O(重叠式I / O)Completion port(完成端口) 一. 简介套接字模型的出现,是为了解决套接字模式存在的

Winsock IO模型之IOCP模型

http://blog.csdn.net/lostyears/article/details/7436802 Windows平台上伸缩性最好的一种I/O模型莫过IOCP了,不过设计和实现起来比较复杂一些.针对成千上万个套接字的并发处理,IOCP采用了线程池+队列+重叠结构的内核机制完成任务.需要说明的是IOCP其实不仅可以接受套接字对象句柄,还可以接受文件对象句柄等. 为避免线程上下文切换,它采用了线程池.除此之外,在基于事件模型或重叠模型中不得不遇到WSAWaitForMultipleEven

走入计算机的第三十九天(python终结篇之IO模型)

一.IO模型 1.IO模型分类 1.阻塞IO--------blocking IO 2.非阻塞IO------nonblocking IO 3. 多路复用IO------- multiplexing 4.信号驱动IO-------signal driven IO (工作中不会使用到,只是作为了解) 5.异步IO------- asynchronous IO 2.通常情况下IO默认操作分为两个阶段(默认都是阻塞IO) 1.准备等待数据阶段,相当于请求操作系统是否有数据发送过来(调用IO操作). 2