socket通信之六:Overlapped I/O 事件通知模型实现的客户/服务器模型

1.基于事件通知模型的Overlapped I/O(重叠IO模型)


概括一点说,重叠模型是让应用程序使用重叠数据结构(WSAOVERLAPPED),一次投递一个或多个Winsock I/O请求。针对这些提交的请求,在它们完成之后,应用程序会收到通知,于是就可以通过自己另外的代码来处理这些数据了。


      需要注意的是,有两个方法可以用来管理重叠IO请求的完成情况(就是说接到重叠操作完成的通知):

  1. 事件对象通知(event object notification)
  2. 完成例程(completion routines) ,注意,这里并不是完成端口


这一篇实现基于事件对象通知的重叠I/O模型。


既然是基于事件通知,就要求将Windows事件对象与WSAOVERLAPPED结构关联在一起(WSAOVERLAPPED结构中专门有对应的参数),发送接收数据的函数参数中都有一个Overlapped参数,我们可以假设是把我们的WSARecv这样的操作操作“绑定”到这个重叠结构上,提交一个请求,其他的事情就交给重叠结构去操心,而其中重叠结构又要与Windows的事件对象“绑定”在一起,这样我们调用完WSARecv以后就可以“坐享其成”,等到重叠操作完成以后,自然会有与之对应的事件来通知我们操作完成,然后我们就可以来根据重叠操作的结果取得我们想要德数据了。


socket连接,WSAOVERLAPPED重叠IO结构,事件对象之间的关系如下图:


socket通信之六:Overlapped I/O 事件通知模型实现的客户/服务器模型_第1张图片



可以发现每建立一个socket连接时需要至少创建一个WSAOVERLAPPED结构和它关联,而每个WSAOVERLAPPED需要关联一个WSAEVENT类型的事件对象。所以为了实现多个客户端和服务器端通信,我们也需要像上一篇select模型一样建立一个类来管理多个socket和它们对应的WSAOVERLAPPED结构,WSAEVENT结构。


2.基本的函数和数据结构


2.1.  WSAOVERLAPPED结构


这个结构自然是重叠模型里的核心,它是这么定义的

typedef struct _WSAOVERLAPPED {

  DWORD Internal;

  DWORD InternalHigh;

  DWORD Offset;

  DWORD OffsetHigh;

  WSAEVENT hEvent;      // 唯一需要关注的参数,用来关联WSAEvent对象
       } WSAOVERLAPPED, *LPWSAOVERLAPPED;


我们需要把WSARecv等操作投递到一个重叠结构上,而我们又需要一个与重叠结构“绑定”在一起的事件对象来通知我们操作的完成,看到了和hEvent参数,不用我说你们也该知道如何来来把事件对象绑定到重叠结构上吧?大致如下:


WSAEVENT event;                   // 定义事件
WSAOVERLAPPED AcceptOverlapped ; // 定义重叠结构
event = WSACreateEvent();         // 建立一个事件对象句柄
ZeroMemory(&AcceptOverlapped, sizeof(WSAOVERLAPPED)); // 初始化重叠结构
AcceptOverlapped.hEvent = event;    

2.2.WSARecv系列函数


在重叠模型中,接收数据就要靠它了,它的参数也比recv要多,因为要用到重叠结构,它是这样定义的:

        int WSARecv(
                        SOCKET s,                      // 当然是投递这个操作的套接字
                        LPWSABUF lpBuffers,          // 接收缓冲区,与Recv函数不同,这里需要一个由WSABUF结构构成的数组
                        DWORD dwBufferCount,        // 数组中WSABUF结构的数量
                        LPDWORD lpNumberOfBytesRecvd,  // 如果接收操作立即完成,这里会返回函数调用所接收到的字节数
                        LPDWORD lpFlags,             // 设置为0即可
                        LPWSAOVERLAPPED lpOverlapped,  // “绑定”的重叠结构
                        LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine // 完成例程中将会用到的参数,我们这里设置

你可能感兴趣的:(C++)