windows iocp

// test.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
// winsock 2 的头文件和库
#include <winsock2.h>
#include <MSWSock.h>
#include <iostream>
#include <list>
#include <windows.h>

using namespace std;

#pragma comment(lib,"ws2_32.lib")

enum IOOperType{  
     TYPE_RECV,            //数据接收事件
     TYPE_SEND,            //数据发送事件
};

struct IO_DATA
{
    OVERLAPPED            overLapped;
    WSABUF                wsabuf;
    char                buf[1024];
    IOOperType            operType;
    SOCKET                client;

    void Init(IOOperType type,const SOCKET& sck,int len = 0)
    {
        memset(&overLapped, 0, sizeof(overLapped));
        operType = type;
        wsabuf.buf = buf;
        memset(buf, 0, sizeof(buf));
        if (0 == len)
        {
            wsabuf.len = sizeof(buf);
        }
        else
        {
            wsabuf.len = len;
        }
        client = sck;
    }
};

list<IO_DATA*> g_listUnUseData;
list<IO_DATA*>    g_listData;
CRITICAL_SECTION g_cs;
long            g_nCount = 0;

IO_DATA* GetOverlapped()
{
    EnterCriticalSection(&g_cs);
    IO_DATA* pTmp = NULL;
    if (g_listUnUseData.size()>0)
    {
        pTmp = g_listUnUseData.back();
        g_listUnUseData.pop_back();
    }
    else
    {
        pTmp = new(IO_DATA);
        g_listData.push_front(pTmp);
    }
    LeaveCriticalSection(&g_cs);
    
    return pTmp;
}

void RecycleOverlapped(IO_DATA* pData)
{
    EnterCriticalSection(&g_cs);
    g_listUnUseData.push_front(pData);
    LeaveCriticalSection(&g_cs);
}

DWORD _stdcall WorkerThread(LPVOID lParam)
{
    HANDLE* pHandle = (HANDLE*)lParam;
    IO_DATA* lpIOContext = NULL;
    DWORD nBytes = 0;
    DWORD dwFlags = 0;
    int nRet = 0;

    DWORD dwIoSize = 0;
    void * lpCompletionKey = NULL;
    LPOVERLAPPED lpOverlapped = NULL;
    while (1)
    {
        GetQueuedCompletionStatus(*pHandle, &dwIoSize, (LPDWORD)&lpCompletionKey, &lpOverlapped, INFINITE);
        lpIOContext = (IO_DATA*)lpOverlapped;
        if (dwIoSize == 0)
        {
            cout << "Client disconnect" << endl;
            closesocket(lpIOContext->client);
            
            RecycleOverlapped(lpIOContext);
            continue;
        }

        switch (lpIOContext->operType)
        {
        case TYPE_RECV:
        {
            InterlockedIncrement(&g_nCount);
            if (0 == g_nCount % 100000)
                cout << g_nCount << endl;

            lpIOContext->Init(TYPE_RECV, lpIOContext->client);

            DWORD nBytes = 1024, dwFlags = 0;
            int nRet = WSARecv(lpIOContext->client, &lpIOContext->wsabuf, 1, &nBytes, &dwFlags, &lpIOContext->overLapped, NULL);

            if (nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
                cout << "WASRecv Failed::Reason Code::" << WSAGetLastError() << endl;
                closesocket(lpIOContext->client);
                RecycleOverlapped(lpIOContext);
            }

            IO_DATA* pData = GetOverlapped();
            pData->Init(TYPE_SEND, lpIOContext->client);
            sprintf_s(pData->buf, "hello %s", lpIOContext->buf);
            DWORD SendBytes = strlen(pData->buf);
            pData->wsabuf.len = SendBytes;

            nRet = WSASend(pData->client, &pData->wsabuf, 1,
                &SendBytes, 0, &pData->overLapped, NULL);

            if (nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
                cout << "WSASend Failed::Reason Code::" << WSAGetLastError() << endl;
                closesocket(lpIOContext->client);
                RecycleOverlapped(lpIOContext);
            }
        }
            break;
        case TYPE_SEND:
        {
            RecycleOverlapped(lpIOContext);
        }
            break;
        default:
            break;
        }
    }
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    InitializeCriticalSection(&g_cs);
    //listen socket需要将accept操作投递到完成端口,因此,listen socket属性必须有重叠IO
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    SOCKET hSocket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (hSocket == INVALID_SOCKET)
    {
        cout << "WSASocket create socket error" << WSAGetLastError() << endl;
        return false;
    }
    int nMaxConcurrency = 8;
    HANDLE hHandleIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nMaxConcurrency);
    //创建并设置IOCP并发线程数量
    if (INVALID_HANDLE_VALUE == hHandleIocp)
    {
        cout << "IOCP create error,error code " << WSAGetLastError() << endl;
        return false;
    }

    sockaddr_in service;
    service.sin_family = AF_INET;
    service.sin_port = htons(6666);
    service.sin_addr.s_addr = inet_addr("127.0.0.1");
    
    if (bind(hSocket, (sockaddr*)&service, sizeof(service)) == SOCKET_ERROR)
    {
        cout << "bind() error,error code " << WSAGetLastError() << endl;
        return false;
    }
    cout << "bind ok!" << endl;

    if (listen(hSocket, SOMAXCONN) == SOCKET_ERROR)
    {
        cout << "listen() error,error code " << WSAGetLastError() << endl;
        return false;
    }
    cout << "listen ok!" << endl;


    HANDLE* hHandle = new HANDLE[nMaxConcurrency];
    for (int i = 0; i < nMaxConcurrency; ++i)
    {
        DWORD dwThreadID = 0;
        hHandle[i] = CreateThread(NULL, 0, WorkerThread, &hHandleIocp, 0, &dwThreadID);
    }

    while (1)
    {
        sockaddr* addr = NULL;
        int* addrLen = 0;
    
        SOCKET client = accept(hSocket, addr, NULL);
        if (CreateIoCompletionPort((HANDLE)client, hHandleIocp, 0, 0) == NULL)
        {
            cout << "Binding client socket to completionPort fail" << GetLastError() << endl;
            closesocket(client);
            continue;
        }

        IO_DATA* data = GetOverlapped();
        data->Init(TYPE_RECV, client);

        DWORD nBytes = 1024, dwFlags = 0;
        int nRet = WSARecv(client, &data->wsabuf, 1, &nBytes, &dwFlags, &data->overLapped, NULL);

        if (nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
            cout << "WASRecv Failed::Reason Code::" << WSAGetLastError() << endl;
            closesocket(client);

            RecycleOverlapped(data);
        }
    }

    closesocket(hSocket);
    WSACleanup();
    return 0;
}

// client.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include <iostream>
#include <WinSock2.h>
using namespace std;

#pragma comment(lib,"ws2_32.lib")


DWORD _stdcall WorkThread(LPVOID)
{
    sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(6666);
    server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

    const int num = 200;
    SOCKET client[num];

    for (int i = 0; i < num; ++i)
    {
        client[i] = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        int flag;
        flag = connect(client[i], (sockaddr*)&server, sizeof(server));
        if (flag < 0){
            cout << "error!" << endl;
            return 0;
        }
    }
    cout << "connect success" << endl;
    while (1){
        int nPos = rand() % 100;
        char buffer[1024] = "JFKL;AJKFD;LASFKJDSA;KFDS";

        send(client[nPos], buffer, 1024, 0);
        memset(buffer, NULL, sizeof(buffer));

        int rev = recv(client[nPos], buffer, 1024, 0);
        if (rev == 0)
        {
            continue;
        }

    }
    for (int i = 0; i < num; ++i)
    {
        closesocket(client[i]);
    }
    
    return 0;
}

int _tmain(int argc, _TCHAR* argv[])
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    DWORD dwThreadID;
    HANDLE handle[5];
    for (int i = 0; i < 5; ++i)
    {
        handle[i] = CreateThread(NULL, 0, WorkThread, NULL, 0, &dwThreadID);
    }
    
    WaitForMultipleObjects(5, handle, TRUE, -1);
    WSACleanup();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值