重叠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;
}

 

posted @ 2017-07-07 11:10  菜鸟也有高飞的时候  阅读(367)  评论(0编辑  收藏  举报