第22章 重叠I/O模型
第21章异步处理的并非I/O,而是通知!
http://blog.csdn.net/xiaxzhou/article/details/77116124
- 重叠I/O
一个线程内部同时向多个目标传输数据引起的I/O重叠现象称为重叠I/O。
为了完成这项任务,调用函数应立即返回,只有这样才能发送后续的数据。从结果上看,利用上述模型收发数据时,最重要的前提条件就是异步I/O。而且,为了完成异步I/O,调用的I/O函数应以非阻塞模式工作。
本章重点不是I/O本身,而是如何确认I/O完成时的状态。不管是输入输出,只要是非阻塞模式的,就要另外确认执行的结果。
创建适用于重叠I/O的套接字:WSASocket()
执行重叠I/O的函数:WSASend()、WSARecv()
WSASend函数调用过程中,函数返回时间点和数据传输完成时间点并非总不一致。
如果输出缓冲是空的,且传输的数据并不大,则函数调用后可立即完成数据传输。此时WSASend函数将返回0,函数第四个参数将保存实际传输的数据大小的信息。
反之,WSASend函数返回后仍需要传输数据,则返回SOCKET_ERROR,并将WSA_IO_PENDING注为错误代码,该代码可通过WSAGetLastError函数得到。这是可通过WSAGetOverlappedResult()获取实际传输的数据大小。
两种方法重叠I/O的I/O完成确认:
1 利用WSASend、WSARecv第六个参数:基于事件对象
2 利用WSASend、WSARecv第七个参数:基于Completion Routine
- 事件对象
1 完成I/O时,WSAOVERLAPPED结构体变量引用的事件对象将变为signaled状态。
2 为了验证I/O的完成和完成结果,需要调用WSAGetOverlappedResult函数。
使用WSASocket时返回值错误:10049
把:server_addr.sin_addr.s_addr=inet_addr(INADDR_ANY);
改为:server_addr.sin_addr.s_addr=inet_addr(“127.0.0.1”);
错误解决。不明白为何会这样
基于事件对象:
服务器端:
#include "stdafx.h"
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
using namespace::std;
#define BUF_SIZE 1024
void ErrorHanding(char * message);
void main()
{
WSADATA wsaData;
SOCKET hLisnSock,hRecvSock;
SOCKADDR_IN lisnAdr,recvAdr;
int recvAdrSz;
WSABUF dataBuf; //缓冲数据地址和大小等信息
WSAEVENT evObj; //事件对象
WSAOVERLAPPED overlapped; //只需关注:保存的事件对象 多个传输目标需要多个变量
char buf[BUF_SIZE];
DWORD recvBytes = 0, flags = 0;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)//加载库并获取库信息填至wsaData
ErrorHanding("socket start error!");
//参数:协议族,套接字传输方式,使用的协议,WSA_PROTOCOL_INFO结构体地址/不需要时传null,扩展保留参数,套接字属性信息
hLisnSock = WSASocket(PF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED);