极速论坛's Archiver

niuboy 发表于 2008-4-4 07:27

用完成端口写的echo server 服务器

完成端口网上的例子很多,但觉得都挺复杂的

写了一个简化版的,方便学习,也加了注释。

有任何问题,欢迎跟我讨论。

========代码来了=========


[code]#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();

}[/code]

niuboy 发表于 2008-4-4 07:48

代码测试可用,写得也不错。

转角看火星 发表于 2008-6-4 22:33

怎么就吸引不到我呢。

怎么就吸引不到我呢,[url=http://www.ccswill.com]cctv camera[/url]
[url=http://www.ccswill.com]video intercom[/url]更别说欣赏了。

qian7912 发表于 2008-7-8 04:43

吐血支持

[color=black]050◎不想当厨子的[/color][url=http://chuanqishijie.fsifu.com/][color=black]传奇世界私服[/color][/url][color=black]裁缝,不是好司机。
051◎时间是最好的老师,但遗憾的是——最后他把所有的学生都弄死了。
052◎去西安出差的[/color][url=http://chuanqi.fsifu.com/][color=black]传奇私服[/color][/url][color=black]路上,一位大连老兄一阵狂吹大连多好多好,然后说大连建市一百周年的时候举行了很隆重的庆祝活动云云,然后问了旁边一人:“西安建市一百周年有什么庆祝活动没有?”旁边几位西安的[/color][url=http://zhengtu.fsifu.com/][color=black]征途私服[/color][/url][color=black]哥们一愣,过了一会儿,逼出一句话来:“我记得西安建市600年的时候搞了一个‘烽火戏诸侯’吧……”
053◎钻石恒久远,一颗就破产!
054◎和谐校园里,骑自行车的也许是[/color][url=http://moyu.fsifu.com/][color=black]魔域私服[/color][/url][color=black]位博导,而开奔驰的则可能是个后勤……
055◎是金子,总会花光的;是镜子,总会反光的……
056◎我女友不当尼姑的原因[/color][url=http://www.suzhoulongjia.com/][color=black]苏州模具[/color][/url][color=black]是她四级没过,庵里不收。
057◎明星脱一点就能更出名,我脱的光光的却被抓起来了!
058◎看一漂亮MM,苦无搭讪办法,路旁一砖头,拣起,上前,“同学,这是你掉的吧?”[/color]

页: [1]

Powered by Discuz! Archiver 7.2  © 2001-2009 Comsenz Inc.