IOCP模型Demo
首页 > 后端开发    作者:StanWind   2016年9月29日 1:42 星期四   热度:3032°   百度已收录  
时间:2016-9-29 1:42   热度:3032° 
#include <winsock2.h>
#include <stdio.h>
#include <process.h>
#include <time.h>
#pragma comment(lib,"ws2_32")

#define DEFAULT_BUFLEN 1024

typedef struct
{
    OVERLAPPED Overlapped;
    WSABUF DataBuf;
    CHAR Buffer[DEFAULT_BUFLEN];
    DWORD BytesRECV;
}PER_IO_DATA,*LPPER_IO_DATA;

typedef struct
{
    SOCKET Socket;
}PER_HANDLE_DATA,*LPPER_HANDLE_DATA;
DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID);
int main()
{
    SOCKADDR_IN InternetAddr;
    SOCKET ServerSocket = INVALID_SOCKET;
    SOCKET AcceptSocket = INVALID_SOCKET;
    HANDLE CompletionPort;
    SYSTEM_INFO SystemInfo;
    PER_HANDLE_DATA a;
    PER_IO_DATA b;
    LPPER_HANDLE_DATA PerHandleData;
    LPPER_IO_DATA PerIoData;
    DWORD RecvBytes;
    DWORD Flags;
    DWORD ThreadID;
    WSADATA wsaData;
    DWORD Ret;
    int iResult;

    PerIoData = &b;
    PerHandleData =&a;

    if ((CompletionPort=CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,8)) == NULL)
    {
        printf("CreateIoCompletionPort err!\n");
        return -1;
    }

    GetSystemInfo(&SystemInfo);

    for (int i=0;i<(SystemInfo.dwNumberOfProcessors)*2;i++)//创建工作线程循环
    {
        HANDLE ThreadHandle;
        if ((ThreadHandle = CreateThread(NULL,0,ServerWorkerThread,(LPVOID)&CompletionPort,0,&ThreadID)) == NULL)
        {
            printf("创建工作线程i 失败");
            return -1;
        }
        CloseHandle(ThreadHandle);
    }

    if ((Ret = WSAStartup(0x0202,&wsaData)) != 0)
    {
        printf("初始化失败");
        return -1;
    }

    ServerSocket = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);

    if (ServerSocket == INVALID_SOCKET)
    {
        printf("WSASocket() failed with error %d\n",WSAGetLastError());
        return -1;
    }

    InternetAddr.sin_family = AF_INET;
    InternetAddr.sin_addr.s_addr=htonl(INADDR_ANY);
    InternetAddr.sin_port = htons(9000);
    iResult = bind(ServerSocket,(PSOCKADDR)&InternetAddr,sizeof(InternetAddr));
    if (iResult == SOCKET_ERROR)
    {
        printf("bind失败");
        return -1;
    }
    if (listen(ServerSocket,5)==SOCKET_ERROR)
    {
        printf("listen失败");
    }

    printf("TCP server 开始");

    sockaddr_in addrClient;
    int addrClientlen = sizeof(sockaddr_in);

    while (TRUE)
    {
        AcceptSocket = WSAAccept(ServerSocket,(sockaddr *)&addrClient,&addrClientlen,NULL,0);
        if (AcceptSocket == SOCKET_ERROR)
        {
            printf("WSAAccept() 失败");
            return -1;
        }

    //
        PerHandleData = (LPPER_HANDLE_DATA)GlobalAlloc(GPTR,sizeof(LPPER_HANDLE_DATA));
        if (PerHandleData == NULL)
        {
            printf("GlobalAlloc 失败");
            return -1;
        }
        PerHandleData->Socket =AcceptSocket;

        if (CreateIoCompletionPort((HANDLE)AcceptSocket,CompletionPort,(DWORD)PerHandleData,0) == NULL)
        {
            printf("CreateIoCompletionPort 失败");
            return -1;
        }

        PerIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));
        if (PerHandleData == NULL)
        {
            printf("GlobalAlloc 失败");
            return -1;
        }

        ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
        PerIoData->BytesRECV = (DWORD)0;
        PerIoData->DataBuf.len = DEFAULT_BUFLEN;
        PerIoData->DataBuf.buf = PerIoData->Buffer;
        Flags = 0;

        iResult = WSARecv(AcceptSocket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);

        if (iResult == SOCKET_ERROR)
        {
            if (WSAGetLastError()!=ERROR_IO_PENDING)
            {
                printf("wsarecv 错误");
                return -1;
            }
        }
    }
    return 0;
}

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPortID)
{
    HANDLE CompletionPort = *(HANDLE*)CompletionPortID;
    DWORD BytesTransferred;
    LPPER_HANDLE_DATA PerHandleData;
    LPPER_IO_DATA PerIoData;
    DWORD RecvBytes;
    DWORD Flags;
    int iResult;

    while(true)
    {
        if (GetQueuedCompletionStatus(CompletionPort,&BytesTransferred,(LPDWORD)&PerHandleData,(LPOVERLAPPED *)&PerIoData,INFINITE) == 0)
        {
            printf("GetQueuedCompletionStatus 失败");
            return 0;
        }

        if (BytesTransferred == 0)
        {
            printf("Closing socket %d\n",PerHandleData->Socket);

            if (closesocket(PerHandleData->Socket) == SOCKET_ERROR)
            {
                printf("close err");
                return 0;
            }

            GlobalFree(PerHandleData);
            GlobalFree(PerIoData);
            continue;
        }

        if (PerIoData->BytesRECV == 0)
        {
            PerIoData->BytesRECV = BytesTransferred;
        }

        printf("\nBytes received: %d\n",BytesTransferred);

        PerIoData->BytesRECV = 0;
        Flags = 0;
        ZeroMemory(&(PerIoData->Overlapped),sizeof(OVERLAPPED));
        PerIoData->DataBuf.len = DEFAULT_BUFLEN;
        PerIoData->DataBuf.buf = PerIoData->Buffer;
        iResult =WSARecv(PerHandleData->Socket,&(PerIoData->DataBuf),1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
        if (iResult == SOCKET_ERROR)
        {
            if (WSAGetLastError()!= ERROR_IO_PENDING)
            {
                printf("WSARecv err:%d",WSAGetLastError());
                return 0;
            }
        }
        printf("%s",PerIoData->DataBuf.buf);
        return 0;
    }
}
二维码加载中...
本文作者:StanWind      文章标题: IOCP模型Demo
本文地址:https://www.stanwind.com/post/16
版权声明:若无注明,本文皆为“Make it Better”原创,转载请保留文章出处。

返回顶部    首页    手机版本    后花园  
版权所有:Make it Better    站长: StanWind    赣ICP备17014296号