WinSock重叠IO模型一

来源:互联网 发布:农村三级卫生服务网络 编辑:程序博客网 时间:2024/04/27 23:59

  WinSock的重叠IO模型也就是重叠IO的一个特例罢了。其实就是把套接字当成文件来操作。在重叠IO中,如果读大文件的时候,为了不在那里干等。告诉系统,我先去下两盘象棋,你读完了,告诉我一下。下棋时窗口是全屏的,读完后,弹一个对话框出来告诉我下吧。恩,下棋,真是浪费时间的事,得戒掉啊。

   WinSock中的重叠模型也是如此,告诉系统,有人发数据过来的时候通知我哈。我现在干点别的事太无聊了。于是就可以耍了。但是,要让系统通知你,你得把你电话号码给它吧,不让有到时后它在那里找你啊。下面就来看看在重叠模型中,是怎样做这个准备工作的。

 

1、创建套接字,绑定,监听,发现有客户端接入,好了,现在有人和我下棋了。大战三百回合,恩,才没几盘,对方要去吃饭,又不知道它吃快,吃慢,让我干等它吃饭,没门,还是去找其他人和我下吧。但是他技术还不错,让他吃好后叫我吧,还没把他杀过瘾呢。于是告诉它来的时候,给我QQ发过抖动窗口我就知道了。一边把QQ开在那里等着,一边和别人下。

2、过了好一会,QQ聊天窗口抖动了,小丫的,终于来了。继续我们的伟大事业吧。该重叠模型和上一个WSAEventSelect模型很类似,只是功能强点,也要难理解点。下面这个结构,就相当于实现QQ聊天窗口抖动这一事件功能。

WSAOVERLAPPED结构
这个结构自然是重叠模型里的核心,用于绑定套接字、操作以及操作对应的事件。
typedef struct _WSAOVERLAPPED {
        DWORD Internal;
       DWORD InternalHigh;
       DWORD Offset;    //文件操作中想要开始的低偏移量,网络中不用
       DWORD OffsetHigh; //文件操作中想要开始的高偏移量,网络中不用
       WSAEVENT hEvent;      // 网络编程中唯一需要关注的参数,用来关联WSAEvent对象
} WSAOVERLAPPED, *LPWSAOVERLAPPED;

很明显,我们只管最后一个参数hEvent,其他都是系统自己使用,自己负责处理。就象我们使用QQ一样,不管他是怎么做出来的,它界面上有传送文件、语音聊天、视频聊天这些功能一样我们都不管他,就只管窗口抖动这事。看到抖动就知道棋友终于来了。
最后一个参数是事件对象句柄,和WSAEventSelect模型一样,使WSACreateEvent创建一个对象复制给它就行了。

 

3、商量好用抖动窗口作为开始下棋的标记,于是把QQ聊天窗口打开就可以做其它事了,现在商量好有消息过来就通知,就可以调用WSASend、WSARecv、WSASendTo、WSARecvFrom等函数等待消息来时返回。其实就是WSAOVERLAPPED结构中的hEvent事件有信号了。到这感觉到重叠IO和WSAEventSelect模型是一样的啊,只不过是把前面说的事件数组,而现在这使用结构而已。但是很明显,重叠模型的优点我们还没有开始展示呢。

4、重叠IO模型是我们在调用WSARecv等函数的时候,已经把接收数据的地址告诉给了系统,它返回时,已经把我们给它的包包填好了,而不像在WSAEventSelect中,让我们自己去读。正因为前面都要我们在收到可以读消息的时候才去读,而现在是消息告诉我们我已经把刚到来的消息数据读出放在XX缓冲区中,你自己想怎们使用自己看作办时还有点不习惯了。于是就要看看它究竟是怎们实现的呢。

int WSARecv(
       SOCKET s,                      // 当然是投递这个操作的套接字
       LPWSABUF lpBuffers, // 接收缓冲区,是WSABUF结构构成的数组 用于接收发送过来的数据
       DWORD dwBufferCount,        // 数组中WSABUF结构的数量
       LPDWORD lpNumberOfBytesRecvd, // 如果接收操作立即完成,返回函数调用所接收到的字节数
       LPDWORD lpFlags,             // 说来话长了,我们这里设置为0 即可
       LPWSAOVERLAPPED lpOverlapped, // “绑定”的重叠结构 
       LPWSAOVERLAPPED_COMPLETION_ROUTINE lpCompletionRoutine); // 完成例程中将会用到的参数,

                                                               //我们这里设置为NULL

该函数就好象再说,现在我要在套接字s上等待对方给我发数据了,如果对方发数据过来后把他放在lpBuffers中,并且使lpOverlapped.hEvent有信号,让我们对该消息事件进行处理。

 

5、现在已经商量好了,就只有等待对方消息过来了。

DWORD WSAWaitForMultipleEvents(
       DWORD cEvents,                        // 等候事件的总数量
       const WSAEVENT* lphEvents,            // 事件数组的指针
       BOOL fWaitAll, //当设置为 TRUE,事件数组中所有事件被传信的时候函数才会返回
                    // FALSE则任何一个事件被传信函数都要返回,此时设为FALSE
       DWORD dwTimeout,    // 超时时间,如果超时,函数会返回 WSA_WAIT_TIMEOUT
                          // 如果设置为0,函数会立即返回
       BOOL fAlertable);   // 在完成例程中会用到这个参数,这里我们先设置为FALSE

上面是昨晚写的,睡着了
电脑开了一晚上了,哈哈