IOCP

1.包含以下内容
#define WIN32_LEAN_AND_MEAN      //定义宏,不会出现error C2011: 'fd_set' : 'struct' type redefinition等错误
#define VC_EXTRALEAN

#include <windows.h>
#include <winsock2.h>
#include "iostream"
#pragma comment(lib, "Ws2_32.lib")

2.定义结构体

typedef struct         
{
 OVERLAPPED Overlapped;
 WSABUF DataBuf;
 CHAR Buffer[DATA_BUFSIZE];                    
 DWORD BytesSEND;                                 //发送字节数
 DWORD BytesRECV;                                
} PER_IO_OPERATION_DATA, * LPPER_IO_OPERATION_DATA;


typedef struct
{
 SOCKET Socket;
} PER_HANDLE_DATA, * LPPER_HANDLE_DATA;

3.初始化socket

WORD wVersionRequested;
 WSADATA wsaData;
 int Ret;
 
 wVersionRequested = MAKEWORD(2,0);
 //err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
 if ((Ret = WSAStartup(0x0202, &wsaData)) != 0)
   {
      printf("WSAStartup failed with error %d\n", Ret);
      return;
   }
4.申请PER_IO_DATA
//使用NEW不可以。
//PerHandleData = new PER_HANDLE_DATA;
  if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
  {
   printf("GlobalAlloc() failed with error %d\n", GetLastError());
   return;
  }     

5.一个例子

// server.cpp
#include  < winsock2.h >
#include 
< windows.h >
#include 
" socketapi.h "
#include 
" socketnotify.h "
#include 
" iostream "

using   namespace  std;
#pragma comment(lib, 
" Ws2_32 " )

#define  OP_READ     0
#define  OP_WRITE    1
#define  OP_ACCEPT   2
#define  DATA_BUFSIZE 1024



typedef 
struct
{
    OVERLAPPED Overlapped;
    WSABUF DataBuf;
    CHAR Buffer[DATA_BUFSIZE];                     
    DWORD BytesSEND;                                 
//发送字节数
    DWORD BytesRECV;                                 
}
 PER_IO_OPERATION_DATA,  *  LPPER_IO_OPERATION_DATA;


typedef 
struct
{
    SOCKET Socket;
}
 PER_HANDLE_DATA,  *  LPPER_HANDLE_DATA;

 
DWORD __stdcall CompletionRoutine(LPVOID Param);
int  main()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    
int Ret;
    
    wVersionRequested 
= MAKEWORD(2,0);
    
//err = WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
    if ((Ret = WSAStartup(0x0202&wsaData)) != 0)
   
{
      printf(
"WSAStartup failed with error %d\n", Ret);
      
return;
   }
 
    HANDLE    CompletionPort;
    LPPER_HANDLE_DATA PerHandleData ;
    LPPER_IO_OPERATION_DATA     PerIoData ;
    SOCKADDR_IN InternetAddr;
    DWORD RecvBytes;
    DWORD Flags;
    SOCKET server;
    SOCKET Accept;
    
if ((server = WSASocket(AF_INET, SOCK_STREAM, 0, NULL, 0,
        WSA_FLAG_OVERLAPPED)) 
== INVALID_SOCKET)
    
{
        printf(
"WSASocket() failed with error %d\n", WSAGetLastError());
        
return;
    }

    InternetAddr.sin_family 
= AF_INET;
    InternetAddr.sin_addr.s_addr 
= htonl(INADDR_ANY);
    InternetAddr.sin_port 
= htons(8000);
    
if (bind(server, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr)) == SOCKET_ERROR)
    
{
        printf(
"bind() failed with error %d\n", WSAGetLastError());
        WSACleanup();
        
return;
    }
   
    
    
if (listen(server, 5== SOCKET_ERROR)
    
{
        printf(
"listen() failed with error %d\n", WSAGetLastError());
        WSACleanup();
        
return;
    }

    
//    server.set_port(8000);
    
//    server.listen();
    /**////////////////////////////
    //取得系统中CPU的数目,创建和CPU数目相等的线程,如果事先估计到完成端口处理线程会堵塞,
    
//可以考虑创建 SysInfo.dwNumberOfProcessors*2个线程。一般在单处理器上创建和CPU数目相等
    
//的线程就可以了
    
//获得CPU个数
    SYSTEM_INFO sysInfo;    
    ZeroMemory(
&sysInfo,sizeof(SYSTEM_INFO));
    ZeroMemory(
&wsaData,sizeof(WSADATA));    
    GetSystemInfo(
&sysInfo);    
    
int nNumberOfConcurrent = sysInfo.dwNumberOfProcessors * 2+2;    
    
    CompletionPort 
= CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, nNumberOfConcurrent);
    
if (NULL == CompletionPort)
    
{
        cout 
<< "CreateIoCompletionPort() failed: " << GetLastError() << endl;
        
        
return ;
    }

    
    PER_IO_OPERATION_DATA per_io_data;
    
    cout
<<"port:"<<CompletionPort<<endl;
    HANDLE     m_hThreadArray[
8];
    
for (int i=0; i<1; i++)
    
{
        m_hThreadArray[i] 
= CreateThread(NULL, 0, CompletionRoutine, (LPVOID)CompletionPort, 0, NULL);
        
if (NULL == m_hThreadArray[i])
        
{
            
while (i>0)
            
{
                CloseHandle(m_hThreadArray[i
-1]);
                m_hThreadArray[i
-1= INVALID_HANDLE_VALUE;
                i
--;
            }
//end of while
            
            cout 
<< "CreateThread() failed: " << GetLastError() << endl;
            CloseHandle(CompletionPort);
            
            
            
return  ;
        }

    }
//end of for
    
    Sleep(
1000);
    
while(1)
    
{
        cout
<<"waiting for accept "<<endl;
        
//int sClient = server.accept();
        
        
if ((Accept = WSAAccept(server, NULL, NULL, NULL, 0)) == SOCKET_ERROR)
        
{
            printf(
"WSAAccept() failed with error %d\n", WSAGetLastError());
            
return;
        }

        
        cout
<<"accetp :"<<Accept<<endl;
        
        
//PerHandleData = new PER_HANDLE_DATA;
        if ((PerHandleData = (LPPER_HANDLE_DATA) GlobalAlloc(GPTR, sizeof(PER_HANDLE_DATA))) == NULL)
        
{
            printf(
"GlobalAlloc() failed with error %d\n", GetLastError());
            
return;
        }
      
        PerHandleData
->Socket = Accept;
        
if(CreateIoCompletionPort((HANDLE)Accept, CompletionPort, (DWORD)PerHandleData, 0== NULL)
        
{
            printf(
"CreateIoCompletionPort failed with error %d\n", GetLastError());
            
return ;
            
        }

        
//PerIoData  = new PER_IO_OPERATION_DATA;
        
//
        
//清管子的数据结构,准备往里面灌数据
        
//
        if ((PerIoData = (LPPER_IO_OPERATION_DATA) GlobalAlloc(GPTR,sizeof(PER_IO_OPERATION_DATA))) == NULL)
        
{
            printf(
"GlobalAlloc() failed with error %d\n", GetLastError());
            
return;
        }

        memset(
&(PerIoData->Overlapped), sizeof(OVERLAPPED),0);
        PerIoData
->BytesSEND = 0;
        PerIoData
->BytesRECV = 0;
        PerIoData
->DataBuf.len = DATA_BUFSIZE;
        PerIoData
->DataBuf.buf = PerIoData->Buffer;
        
        
//
        
//  accept接到了数据,就放到PerIoData中,而perIoData又通过线程中的函数取出,
        
//
        
        RecvBytes 
= 0;
        Flags 
= 0;
        
if (WSARecv(Accept, &(PerIoData->DataBuf), 1&RecvBytes, &Flags,
            
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
        
{
            
if (WSAGetLastError() != ERROR_IO_PENDING)
            
{
                printf(
"main WSARecv() failed with error %d\n", WSAGetLastError());
                WSACleanup();
                
return;
            }

        }

        
//cout<<"recv :"<<PerIoData->Buffer<<endl;
        
        
        
    }

    PostQueuedCompletionStatus(CompletionPort, 
0xFFFFFFFF0, NULL);
    CloseHandle(CompletionPort);
    
    WSACleanup();
 
    cin
>>i;
    
return ;
}


DWORD __stdcall CompletionRoutine(LPVOID Param)
{
    
    HANDLE CompletionPort 
= (HANDLE) Param;
    
    PER_IO_OPERATION_DATA 
*pData = (PER_IO_OPERATION_DATA*)Param;
    
    DWORD BytesTransferred;
    LPOVERLAPPED Overlapped;
    LPPER_HANDLE_DATA PerHandleData;
    LPPER_IO_OPERATION_DATA PerIoData;         
    DWORD SendBytes, RecvBytes;
    DWORD Flags;
    
    
    
    
while(1)
    
{

        
int bSuccess = GetQueuedCompletionStatus(
            CompletionPort,
            
&BytesTransferred,
            (LPDWORD)
&PerHandleData,
            (LPOVERLAPPED 
*&PerIoData,
            INFINITE
            );
        
        cout
<<"----------------------------"<<endl;
        
        
if (0 == bSuccess)
        
{
            
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1&RecvBytes, &Flags,
            
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
            
{
                
int iError = WSAGetLastError();
                
if ( iError!= ERROR_IO_PENDING)
                
{
                    printf(
"client %d closed \n", PerHandleData->Socket);
                    closesocket(PerHandleData
->Socket);
                }

            }

            
            
continue;
        }

        
if (NULL == PerIoData)
        
{
            
//
            cout<<"//PostQueuedCompletionStatus发过来一个空的单句柄数据,表示线程要退出了。"<<endl;
            
//
            return 0;
        }

        Flags 
= 0;
        
if (WSARecv(PerHandleData->Socket, &(PerIoData->DataBuf), 1&RecvBytes, &Flags,
            
&(PerIoData->Overlapped), NULL) == SOCKET_ERROR)
        
{
            
if (WSAGetLastError() != ERROR_IO_PENDING)
            
{
                printf(
"thread WSARecv() failed with error %d\n", WSAGetLastError());
                
return 0;
            }

        }

        
        cout
<<"recv from "<<PerHandleData->Socket<<":"<<PerIoData->Buffer<<endl;
        
        
    }

    
    
return 0;
}


 
#include 
" iostream "

#include 
< winsock2.h >
#include 
< windows.h >
using   namespace  std;
#pragma comment(lib, 
" Ws2_32 " )

 
int  main()
{
    WORD wVersionRequested;
    WSADATA wsaData;
    
int err;
    wVersionRequested 
= MAKEWORD(2,0);
    err 
= WSAStartup(wVersionRequested, &wsaData);//调用Windows Sockets DLL
    if(err != 0)
    
{
         cout
<<"socket init error."<< endl;
    }

    
int i=0;
    
int iRet = 0;
    SOCKET client;

    client 
= socket( AF_INET, SOCK_STREAM, 0); 
    
if( client == INVALID_SOCKET )
    
{
        cout
<< "socket() error"<<WSAGetLastError() <<endl;
    }

    SOCKADDR_IN        saServer;        

    memset(
&saServer,0,sizeof(saServer));

    saServer.sin_family 
= AF_INET;
    saServer.sin_addr.s_addr 
= inet_addr("127.0.0.1");
    saServer.sin_port 
= htons(8000);
    
int nRet = connect(client,(sockaddr*)&saServer, sizeof(saServer));
    
if( iRet == SOCKET_ERROR)
    
{
        cout
<<"connect error"<<endl;
        
return 0;
    }

    
else
    
{
        cout
<<"iRet:"<<iRet<<endl;
        cout
<<"connect success"<<WSAGetLastError()<<endl;
    }

     
char buffer[128]={0};
     
while(1)
     
{
         memset(buffer,
0,128);
         cout
<<"input to send:";
         cin
>>buffer;
         
if(buffer[0== 'q')
            
break;
        
int nBytes;

        
if ((nBytes = send(client, buffer, strlen(buffer),0))
            
== SOCKET_ERROR)
        
{
            
if (GetLastError() == WSAEWOULDBLOCK) 
            
{
                printf(
"Blocking\n");
                Sleep(
100);
                
break;
            }

            
else
            
{
                cout
<<"send error:"<<GetLastError()<<endl;
                closesocket(client);
                
break;
            }

        }

        cout
<<"send success .."<<endl;
     }

     WSACleanup();
    
return 0;
}


Posted on 2008-09-28 13:54 艾凡赫 阅读(615) 评论(0)   编辑  收藏 引用 所属分类: NET WORK

你可能感兴趣的:(IOCP)