Chinaunix首页 | 论坛 | 博客
  • 博客访问: 923897
  • 博文数量: 201
  • 博客积分: 8078
  • 博客等级: 中将
  • 技术积分: 2162
  • 用 户 组: 普通用户
  • 注册时间: 2008-05-20 17:22
文章分类

全部博文(201)

文章存档

2013年(3)

2012年(11)

2011年(34)

2010年(25)

2009年(51)

2008年(77)

分类: WINDOWS

2009-09-09 21:15:22

#include <winsock2.h>
#include <mswsock.h>
#include <windows.h>

#include <iostream>
using namespace std;

int g_ThreadCount;
HANDLE g_hIOCP = INVALID_HANDLE_VALUE;
SOCKET g_ServerSocket = INVALID_SOCKET;

// Maximum Buffer Size
#define MAX_BUFF_SIZE 8192

enum IO_OPERATION{IO_READ,IO_WRITE};

struct IO_DATA{
    WSAOVERLAPPED Overlapped;
    char Buffer[MAX_BUFF_SIZE];
    WSABUF wsabuf;
    int nTotalBytes;
    int nSentBytes;
    IO_OPERATION opCode;
    SOCKET activeSocket;
};

DWORD WINAPI WorkerThread (LPVOID WorkThreadContext) {
    LPWSAOVERLAPPED lpOverlapped = NULL;
    IO_DATA *lpIOContext = NULL;
    WSABUF buffSend;
    DWORD dwRecvNumBytes = 0;
    DWORD dwSendNumBytes = 0;
    DWORD dwFlags = 0;
    DWORD dwIoSize = 0;
       BOOL bSuccess = FALSE;
    int nRet = 0;

       while( 1 ) {
         void * lpCompletionKey = NULL;
         bSuccess = GetQueuedCompletionStatus(g_hIOCP, &dwIoSize,
                                             (LPDWORD)&lpCompletionKey,
                                             (LPOVERLAPPED *)&lpOverlapped,
                                             INFINITE);
         if( !bSuccess )
         {
            cout << "GetQueuedCompletionStatus() failed:"<<GetLastError()<<endl;
            break;
         }

         lpIOContext = (IO_DATA *)lpOverlapped;

         if(dwIoSize == 0) //socket closed?
         {
             cout << "Client disconnect" << endl;
             closesocket(lpIOContext->activeSocket);
             delete lpIOContext;
             continue;
         }

         if(lpIOContext->opCode == IO_READ) // a read operation complete
         {
                lpIOContext->nTotalBytes = lpIOContext->wsabuf.len;
                lpIOContext->nSentBytes = 0;
                lpIOContext->opCode = IO_WRITE;
                dwFlags = 0;
                nRet = WSASend(
                              lpIOContext->activeSocket,
                              &lpIOContext->wsabuf, 1, &dwSendNumBytes,
                              dwFlags,
                              &(lpIOContext->Overlapped), NULL);
                if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                        cout << "WASSend Failed::Reason Code::"<< WSAGetLastError() << endl;
                        closesocket(lpIOContext->activeSocket);
                        delete lpIOContext;
                        continue;
                }
         }
         else if(lpIOContext->opCode == IO_WRITE) //a write operation complete
         {
                lpIOContext->nSentBytes += dwIoSize;
                dwFlags = 0;
                if( lpIOContext->nSentBytes < lpIOContext->nTotalBytes ) {
                    lpIOContext->opCode = IO_WRITE;
                    // A Write operation has not completed yet, so post another
                    // Write operation to post remaining data.
                    buffSend.buf = lpIOContext->Buffer + lpIOContext->nSentBytes;
                    buffSend.len = lpIOContext->nTotalBytes - lpIOContext->nSentBytes;
                    nRet = WSASend (
                                   lpIOContext->activeSocket,
                                   &buffSend, 1, &dwSendNumBytes,
                                   dwFlags,
                                   &(lpIOContext->Overlapped), NULL);

                    if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                        cout << "WASSend Failed::Reason Code::"<< WSAGetLastError() << endl;
                        closesocket(lpIOContext->activeSocket);
                        delete lpIOContext;
                        continue;
                    }
                } else {
                    // Write operation completed, so post Read operation.
                    lpIOContext->opCode = IO_READ;
                    dwRecvNumBytes = 0;
                    dwFlags = 0;
                    lpIOContext->wsabuf.buf = lpIOContext->Buffer,
                    ZeroMemory(lpIOContext->wsabuf.buf,MAX_BUFF_SIZE);
                    lpIOContext->Overlapped.Internal = 0;
                    lpIOContext->Overlapped.InternalHigh = 0;
                    lpIOContext->Overlapped.Offset = 0;
                    lpIOContext->Overlapped.OffsetHigh = 0;
                    lpIOContext->Overlapped.hEvent = NULL;
                    lpIOContext->wsabuf.len = MAX_BUFF_SIZE;
                    nRet = WSARecv(
                                  lpIOContext->activeSocket,
                                  &lpIOContext->wsabuf, 1, &dwRecvNumBytes,
                                  &dwFlags,
                                  &lpIOContext->Overlapped, NULL);
                    if( nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError()) ) {
                        cout << "WASRecv Failed::Reason Code::"<< WSAGetLastError() << endl;
                        closesocket(lpIOContext->activeSocket);
                        delete lpIOContext;
                        continue;
                    }
                }
         }
    }
    return 0;
}

void main (int argc, char * argv[])
{
    { // Init winsock2
        WSADATA wsaData;
        ZeroMemory(&wsaData,sizeof(WSADATA));
        int retVal = -1;
        if( (retVal = WSAStartup(MAKEWORD(2,2), &wsaData)) != 0 ) {
            cout << "WSAStartup Failed::Reason Code::"<< retVal << endl;
            return;
        }
    }

    { //Create socket
        g_ServerSocket = WSASocket(AF_INET,SOCK_STREAM, IPPROTO_TCP, NULL,0,WSA_FLAG_OVERLAPPED);

        if( g_ServerSocket == INVALID_SOCKET ) {
            cout << "Server Socket Creation Failed::Reason Code::" << WSAGetLastError() << endl;
            return;
        }
    }

    { //bind
        sockaddr_in service;
        service.sin_family = AF_INET;
        service.sin_addr.s_addr = htonl(INADDR_ANY);
        service.sin_port = htons(5000);
        int retVal = bind(g_ServerSocket,(SOCKADDR *)&service,sizeof(service));
        if( retVal == SOCKET_ERROR ) {
            cout << "Server Soket Bind Failed::Reason Code::"<< WSAGetLastError() << endl;
            return;
        }
    }

    { //listen
        int retVal = listen(g_ServerSocket, 8);
        if( retVal == SOCKET_ERROR ) {
            cout << "Server Socket Listen Failed::Reason Code::"<< WSAGetLastError() << endl;
            return;
        }
    }

    { // Create IOCP
        SYSTEM_INFO sysInfo;
        ZeroMemory(&sysInfo,sizeof(SYSTEM_INFO));
        GetSystemInfo(&sysInfo);
        g_ThreadCount = sysInfo.dwNumberOfProcessors * 1;
        g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,g_ThreadCount);
        if (g_hIOCP == NULL) {
            cout << "CreateIoCompletionPort() Failed::Reason::"<< GetLastError() << endl;
            return;
        }

           if (CreateIoCompletionPort((HANDLE)g_ServerSocket,g_hIOCP,0,0) == NULL){
            cout << "Binding Server Socket to IO Completion Port Failed::Reason Code::"<< GetLastError() << endl;
            return ;
        }
    }

    { //Create worker threads
        for( DWORD dwThread=0; dwThread < g_ThreadCount; dwThread++ )
        {
            HANDLE hThread;
            DWORD dwThreadId;

            hThread = CreateThread(NULL, 0, WorkerThread, 0, 0, &dwThreadId);
            CloseHandle(hThread);
        }
    }

    { //accept new connection
        while(1)
        {
            SOCKET ls = accept( g_ServerSocket, NULL, NULL );
            if(ls == SOCKET_ERROR) break;
            cout << "Client connected." << endl;

            { //diable buffer to improve performance
                int nZero = 0;
                setsockopt(ls, SOL_SOCKET, SO_SNDBUF, (char *)&nZero, sizeof(nZero));
            }

            if (CreateIoCompletionPort((HANDLE)ls,g_hIOCP,0,0) == NULL){
                cout << "Binding Client Socket to IO Completion Port Failed::Reason Code::"<< GetLastError() << endl;
                closesocket(ls);
            }
            else { //post a recv request
                IO_DATA * data = new IO_DATA;
                ZeroMemory(&data->Overlapped,sizeof(data->Overlapped));
                ZeroMemory(data->Buffer,sizeof(data->Buffer));
                data->opCode = IO_READ;
                data->nTotalBytes = 0;
                data->nSentBytes = 0;
                data->wsabuf.buf = data->Buffer;
                data->wsabuf.len = sizeof(data->Buffer);
                data->activeSocket = ls;
                DWORD dwRecvNumBytes=0,dwFlags=0;
                int nRet = WSARecv(ls,&data->wsabuf, 1, &dwRecvNumBytes,
                                  &dwFlags,
                                  &data->Overlapped, NULL);
                if(nRet == SOCKET_ERROR && (ERROR_IO_PENDING != WSAGetLastError())){
                    cout << "WASRecv Failed::Reason Code::"<< WSAGetLastError() << endl;
                    closesocket(ls);
                    delete data;
                }
            }
        }
    }

    closesocket(g_ServerSocket);
    WSACleanup();
}

阅读(1369) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~