重叠IO

// 重叠IO网络模式.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<WinSock2.h>
#include<windows.h>
#include<iostream>
using namespace std;
#pragma comment (lib,"ws2_32.lib")

#define PORT 6000
#define MSGSIZE 1024

typedef struct
{
    WSAOVERLAPPED overlap;
    WSABUF Buffer;
    char szMessage[MSGSIZE];
    DWORD NumberOfBytesRecvd;
    DWORD Flags;
}PER_IO_OPERATION_DATA,*LPPER_IO_OPERATION_DATA;

int g_iToalComn = 0;

SOCKET g_CliSocketArr[MAXIMUM_WAIT_OBJECTS];
WSAEVENT g_CliEventArr[MAXIMUM_WAIT_OBJECTS];
LPPER_IO_OPERATION_DATA g_pPerIODataArr[MAXIMUM_WAIT_OBJECTS];

DWORD WINAPI WorkerThread(LPVOID lparam);
void Cleanup(int);

bool InitNetEvn()
{
    WSADATA wsa;

    if (WSAStartup(MAKEWORD(2,2),&wsa) != 0)
    {
        cout << "网络环境失败" << endl;
        return false;
    }
    if (LOBYTE(wsa.wVersion)!=2||HIBYTE(wsa.wVersion)!=2)
    {
        cout << "版本号不对" << endl;
        return false;
    }
    return true;
}

int main()
{
    SOCKET sListen, sClient;
    SOCKADDR_IN local, client;
    DWORD dwThreadId;
    int iaddrSize = sizeof(SOCKADDR_IN);
    if (!InitNetEvn())
    {
        return -1;
    }
    sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    local.sin_family = AF_INET;
    local.sin_port = htons(PORT);
    bind(sListen, (sockaddr *)&local, iaddrSize);
    listen(sListen, 3);
    CreateThread(NULL, NULL, WorkerThread, NULL, NULL, &dwThreadId);
    while (TRUE)
    {
        sClient = accept(sListen, (sockaddr *)&client, &iaddrSize);
        printf("Accept client:%s:%d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
        g_CliSocketArr[g_iToalComn] = sClient;

        g_pPerIODataArr[g_iToalComn] = (LPPER_IO_OPERATION_DATA)HeapAlloc(
            GetProcessHeap(),
            HEAP_ZERO_MEMORY,
            sizeof(PER_IO_OPERATION_DATA));

        g_pPerIODataArr[g_iToalComn]->Buffer.len = MSGSIZE;
        g_pPerIODataArr[g_iToalComn]->Buffer.buf = g_pPerIODataArr[g_iToalComn]->szMessage;
        g_CliEventArr[g_iToalComn] = g_pPerIODataArr[g_iToalComn]->overlap.hEvent = WSACreateEvent();

        WSARecv(
            g_CliSocketArr[g_iToalComn],
            &g_pPerIODataArr[g_iToalComn]->Buffer,
            1,
            &g_pPerIODataArr[g_iToalComn]->NumberOfBytesRecvd,
            &g_pPerIODataArr[g_iToalComn]->Flags,
            &g_pPerIODataArr[g_iToalComn]->overlap,
            NULL);
        g_iToalComn++;
    }
    closesocket(sListen);
    WSACleanup();
    return 0;
}

DWORD WINAPI WorkerThread(LPVOID lparam)
{
    int ret, index;
    DWORD cbTransferred;
    while (true)
    {
        //判断出一个重叠IO调用是否完成
        ret = WSAWaitForMultipleEvents(g_iToalComn, g_CliEventArr, FALSE, 1000, FALSE);
        if (ret==WSA_WAIT_TIMEOUT||ret==WSA_WAIT_FAILED)
        {
            continue;
        }
        index = ret - WSA_WAIT_EVENT_0;
        WSAResetEvent(g_CliEventArr[index]);
        WSAGetOverlappedResult(
            g_CliSocketArr[index],
            &g_pPerIODataArr[index]->overlap,
            &cbTransferred,
            TRUE,
            &g_pPerIODataArr[index]->Flags);
        if (cbTransferred==0)
        {
            Cleanup(index);
        }
        else
        {
            g_pPerIODataArr[index]->szMessage[cbTransferred] = ‘\0‘;
            send(g_CliSocketArr[index], g_pPerIODataArr[index]->szMessage,                 cbTransferred, 0);
            WSARecv(
                g_CliSocketArr[index],
                &g_pPerIODataArr[index]->Buffer,
                1,
                &g_pPerIODataArr[index]->NumberOfBytesRecvd,
                &g_pPerIODataArr[index]->Flags,
                &g_pPerIODataArr[index]->overlap,
                NULL);
        }
    }
    return 0;
}

void Cleanup(int index)
{
    closesocket(g_CliSocketArr[index]);
    WSACloseEvent(g_CliEventArr[index]);
    HeapFree(GetProcessHeap(), 0, g_pPerIODataArr[index]);
    if (index<g_iToalComn-1)
    {
        g_CliSocketArr[index] = g_CliSocketArr[g_iToalComn - 1];
        g_CliEventArr[index] = g_CliEventArr[g_iToalComn - 1];
        g_pPerIODataArr[index] = g_pPerIODataArr[g_iToalComn - 1];
    }
    g_pPerIODataArr[--g_iToalComn] = NULL;
}
时间: 2025-01-01 20:36:31

重叠IO的相关文章

Socket重叠IO

1.为什么到现在才弄懂这个 不知道这个Socket重叠IO这种模型是不是socket IO完成端口的基础,不过我感觉,学习一下这个再去学习socket IO完成端口是比较有好处的. 这个Scoket重叠IO我以前记得看过好几次,都没看懂.一部分原因是我没能静态心来写代码,还有更重要的原因就是,Socket重叠他们的结构体参数,还有传参数让人很难理解.下面我将对这些数据结构和参数进行一下讲解 2.初识WSARecv 函数 int WSARecv( SOCKET s,//要接收消息的socket L

重叠IO 模型

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

重叠io操作

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

四.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);假如

windows的重叠IO模型

2019年5月29日 11:58 ? ? 同一线程内部向多个目标传输(或冲多个目标接收)数据引起的IO重叠现象称为"重叠IO".为了完成这项任务,调用IO的函数应立即返回,只有这样才能返送后续数据. 重叠IO收发数据最重要的前提条件就是异步IO. 在windows中重叠IO的重点并非IO本身,而是如何确认IO完成时的状态.因为不管输入还是输出,只要时非阻塞模式的,就要另外确认执行结果.确认执行结果前需要经过特殊的处理过程. ? ? 创建重叠IO套接字 #include <wins

关于Winsock编程中IO重叠的概念

我在看<Windows网络与通信程序设计>(王艳平)这本书时,对重叠IO很不理解,突然就冒出这么一个概念,没一点头绪.就目前的理解做一个整理. 第一种理解:OVERLAPPED,顾名思义为重叠,乍一看会很奇怪,重叠?谁跟谁重叠?似乎在WIN32的Programming中没有这个概念呀?要讨论这个问题就要追溯到对设备I/O的访问中.     在WIN32中,用户不能象以前那样直接对硬件进行访问,使得这一层对开发者而言是个"黑盒",而提供了一组对应的API的接口.让开发者基于提

win32网络模型之重叠I/O

网上大部分重叠I/O的基本概念都讲得很清楚,但是大多讲得不是很深入,实际用起来很多问题.这里只对完成实例的通知进行讨论,对问题进行总结. 重叠IO异步读写后,在某一时刻"完成"后会进行"通知". 什么是"完成": 例如,我们写入500字节,可能只有400字节写入成功,其余的100字节可能由于TCP/IP协议栈缓冲区已满,并没有写入成功,所以完成通知时,你需要进行检查,如果没有全部成功,应该对剩余的部分继续进行异步读写. 什么是"通知&q

手把手教你玩转SOCKET模型之重叠I/O篇(上)

“身为一个初学者,时常能体味到初学者入门的艰辛,所以总是想抽空作点什么来尽我所能的帮助那些需要帮助的人.我也希望大家能把自己的所学和他人一起分享,不要去鄙视别人索取时的贪婪,因为最应该被鄙视的是不肯付出时的吝啬.” ----- 题记  By PiggyXP(小猪) 前   言   其实我首先应该道歉,因为7月份的时候曾信誓旦旦的说要写一套关于SOCKET所有模型的入门文章以及配套代码,不过没想到后天竟然被美女所迷出去度假了,刚刚回来不久......-_-b其实那些模型的配套代码我已经基本写完了,

手把手教你玩转SOCKET模型之重叠I/O篇(下)

四.     实现重叠模型的步骤 作 了这么多的准备工作,费了这么多的笔墨,我们终于可以开始着手编码了.其实慢慢的你就会明白,要想透析重叠结构的内部原理也许是要费点功夫,但是只是学会 如何来使用它,却是真的不难,唯一需要理清思路的地方就是和大量的客户端交互的情况下,我们得到事件通知以后,如何得知是哪一个重叠操作完成了,继而知道 究竟该对哪一个套接字进行处理,应该去哪个缓冲区中的取得数据,everything will be OK^_^. 下面我们配合代码,来一步步的讲解如何亲手完成一个重叠模型.