UDP IOCP ser

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

#include "stdafx.h"
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>

#define PORT     9090
#define MSGSIZE 1024
#pragma comment(lib, "ws2_32.lib")

typedef enum
{
   RECV_POSTED
}OPERATION_TYPE;       //枚举,表示状态
typedef struct
{
WSAOVERLAPPED   overlap;
WSABUF          Buffer;
char            szMessage[MSGSIZE];
struct sockaddr_in addr;
DWORD           NumberOfBytesRecvd;
DWORD           Flags;
OPERATION_TYPE OperationType;
}PER_IO_OPERATION_DATA, *LPPER_IO_OPERATION_DATA;    //定义一个结构体保存IO数据
DWORD WINAPI WorkerThread(LPVOID);
int main()
{
WSADATA                  wsaData;
SOCKET                   sListen, sClient;
SOCKADDR_IN              local, client;
DWORD                    i, dwThreadId;
int                      iaddrSize = sizeof(SOCKADDR_IN);
HANDLE                   CompletionPort = INVALID_HANDLE_VALUE;
HANDLE                   CompletionPort2 = INVALID_HANDLE_VALUE;
SYSTEM_INFO              systeminfo;
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
INT32  fromaddr=sizeof(struct sockaddr_in);
UINT32 iocperrnum,recv=0;
//初始化Socket
WSAStartup(0x0202, &wsaData);
// 初始化完成端口
CompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
// 有几个CPU就创建几个工作者线程
GetSystemInfo(&systeminfo);
for(i = 0; i < systeminfo.dwNumberOfProcessors+2; i++)
{
   CreateThread(NULL, 0, WorkerThread, CompletionPort, 0, &dwThreadId);
}
// 创建套接字
sListen = socket(AF_INET, SOCK_DGRAM, 0);
// 绑定套接字
local.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
local.sin_family = AF_INET;
local.sin_port = htons(PORT);
bind(sListen, (struct sockaddr *)&local, sizeof(SOCKADDR_IN));
// 开始监听!
//listen(sListen, 3);
//主进程的这个循环中循环等待客户端连接,若有连接,则将该客户套接字于完成端口绑定到一起
//然后开始异步等待接收客户传来的数据。
while (TRUE)
{
   // 如果接到客户请求连接,则继续,否则等待。
  // sClient = accept(sListen, (struct sockaddr *)&client, &iaddrSize);
   //client中保存用户信息。
  // printf("Accepted client:%s:%dn", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
   //将这个最新到来的客户套接字和完成端口绑定到一起。
   //第三个参数表示传递的参数,这里就传递的客户套接字地址。
   //最后一个参数为0 表示有和CPU一样的进程数。即1个CPU一个线程
  CompletionPort2= CreateIoCompletionPort((HANDLE)sListen, CompletionPort, ( ULONG_PTR)sListen, 4);
  if(CompletionPort2!=CompletionPort)
	  return 0;
//第三个sClient是传递的参数,传给了后面的线程函数的GetQueuedCompletionStatus了
   
   // 初始化结构体 使用堆内存分配
   lpPerIOData = (LPPER_IO_OPERATION_DATA)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(PER_IO_OPERATION_DATA));
   
   lpPerIOData->Buffer.len = MSGSIZE; // len=1024
   lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
   lpPerIOData->NumberOfBytesRecvd=MSGSIZE;
   lpPerIOData->OperationType = RECV_POSTED; //操作类型
   lpPerIOData->Flags=0;
   
  while(1)
 {
   recv=WSARecvFrom(sListen,
	   &lpPerIOData->Buffer,
	   1,
	   &lpPerIOData->NumberOfBytesRecvd,
	   &lpPerIOData->Flags,
	   (struct sockaddr*)&lpPerIOData->addr,
	   &fromaddr,
	   &lpPerIOData->overlap,
	   NULL
	   );
   
   //Sleep(1); 
  
   iocperrnum= WSAGetLastError();
   /*
   WSARecv(sClient,      //异步接收消息,立刻返回。
     &lpPerIOData->Buffer,   //获得接收的数据
     1,        //The number of WSABUF structures in the lpBuffers array.
     &lpPerIOData->NumberOfBytesRecvd, //接收到的字节数,如果错误返回0
     &lpPerIOData->Flags,   //参数,先不管
     &lpPerIOData->overlap,   //输入这个结构体咯。
     NULL);
	 */
  }
   printf("WSARecv 1 \n");
  }

//向每个工作者线程都发送—个特殊的完成数据包。该函数会指示每个线程都“立即结束并退出”.
PostQueuedCompletionStatus(CompletionPort, 0xFFFFFFFF, 0, NULL);
CloseHandle(CompletionPort);
closesocket(sListen);
WSACleanup();
return 0;
}
//工作者线程有一个参数,是指向完成端口的句柄
DWORD WINAPI WorkerThread(LPVOID CompletionPortID)
{
HANDLE                   CompletionPort=(HANDLE)CompletionPortID;
DWORD                    dwBytesTransferred;
SOCKET                   sClient;
LPPER_IO_OPERATION_DATA lpPerIOData = NULL;
INT32 fromaddr=sizeof(struct sockaddr);
UINT32 recv;
while (TRUE)
{
    printf("enter WorkerThread \n");
         //无限等待咯。不超时的那种。
   if( GetQueuedCompletionStatus(    //遇到可以接收数据则返回,否则等待
    CompletionPort,
    &dwBytesTransferred,    //返回的字数
    (PULONG_PTR)&sClient,           //是响应的哪个客户套接字?
    (LPOVERLAPPED *)&lpPerIOData, //得到该套接字保存的IO信息
	INFINITE)==FALSE  )
	return 1;
   if (dwBytesTransferred == 0xFFFFFFFF)
   {
	   printf("dwBytesTransferred = 0xFFFFFFFF \n");
    return 0;
   }
       if (dwBytesTransferred == 0)
    {
		printf("dwBytesTransferred = 0 \n");
     //失去客户端连接
     closesocket(sClient);
     HeapFree(GetProcessHeap(), 0, lpPerIOData);        //释放结构体
    }
   if(lpPerIOData->OperationType == RECV_POSTED) //如果收到数据
   {


    
     //lpPerIOData->szMessage[dwBytesTransferred] = ' ';//收到的数据最后一位是结束标志
	 
		printf("Message get:%d  ,%s \n",lpPerIOData->addr.sin_addr.S_un.S_addr,lpPerIOData->Buffer.buf);

	 //sendto(sClient, lpPerIOData->Buffer.buf, lpPerIOData->Buffer.len, 0,(struct sockaddr*)&lpPerIOData->addr,sizeof(struct sockaddr)); //将接收到的消息返回
        
     // Launch another asynchronous operation for sClient
    /* memset(lpPerIOData, 0, sizeof(PER_IO_OPERATION_DATA));
       lpPerIOData->Buffer.len = MSGSIZE; // len=1024
	   lpPerIOData->Buffer.buf = lpPerIOData->szMessage;
	   lpPerIOData->NumberOfBytesRecvd=MSGSIZE;
	   lpPerIOData->OperationType = RECV_POSTED; //操作类型
	   lpPerIOData->Flags=0;
	

	   recv=WSARecvFrom(sClient,
	   &lpPerIOData->Buffer,
	   1,
	   &lpPerIOData->NumberOfBytesRecvd,
	   &lpPerIOData->Flags,
	   (struct sockaddr*)&lpPerIOData->addr,
	   &fromaddr,
	   &lpPerIOData->overlap,
	   NULL
	   );
	   printf("recv %d",recv);

	   */
	   /*
     WSARecv(sClient,               //循环接收
       &lpPerIOData->Buffer,
       1,
       &lpPerIOData->NumberOfBytesRecvd,
       &lpPerIOData->Flags,
       &lpPerIOData->overlap,
       NULL);
	   */
   
   }
   }
   return 0;
}
 


























/*
#pragma argsused
#pragma comment(lib,"ws2_32.lib")
#include <stdio.h>
#include <memory.h>
#include <winsock2.h>
#include <iostream>
using namespace std;

#define RECV_POSTED 1001
#define SEND_POSTED 1002

int Init();

HANDLE hCompletionPort;
typedef struct _PER_HANDLE_DATA
{
    SOCKET sock;
}PER_HANDLE_DATA,* LPPER_HANDLE_DATA;

typedef struct _PER_IO_OPERATION_DATA
{
    OVERLAPPED Overlapped;
    WSABUF DataBuff[1];
    char Buff[24];
    BOOL OperationType;
}PER_IO_OPERATION_DATA,* LPPER_IO_OPERATION_DATA;

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPort);

int main(int argc, char* argv[])
{
    LPPER_HANDLE_DATA perHandleData;
    LPPER_IO_OPERATION_DATA ioperdata;
    SYSTEM_INFO siSys;
    SOCKET sockListen;
    struct sockaddr_in addrLocal;
    char buf[24];
    int nRet = 0;
    DWORD nThreadID;
    SOCKET sockAccept;
    DWORD dwFlags;
    DWORD dwRecvBytes;
    int nReuseAddr = 1;

    cout<<"初始环境..."<<endl;
    if(Init() != 0)
        goto theend;

    //创建一个IO完成端口
    cout<<"创建一个IO完成端口"<<endl;
    hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE,NULL,0,0);
    if(hCompletionPort == INVALID_HANDLE_VALUE)
    {
        cout<<"创建IO完成端口失败"<<endl;
        goto theend;
    }
    //获取CPU数目
    GetSystemInfo(&siSys);
    //创建一定数目的工作者线程,本例中以一个处理器一个线程搭配
    for(int i = 0;i<(int)siSys.dwNumberOfProcessors*2;i++)//NumberOfProcessors
    {
        HANDLE hThread;
        hThread = CreateThread(NULL,0,ServerWorkerThread,(LPVOID)hCompletionPort,0,&nThreadID);
        cout<<"创建工作者线程"<<i<<endl;
        CloseHandle(hThread);
    }
    //创建监听SOCKET
    cout<<"创建监听SOCKET"<<endl;
    sockListen = WSASocket(AF_INET,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED);
    if(sockListen == SOCKET_ERROR)
    {
        cout<<"WSASocket错误"<<endl;
        goto theend;
    }

    if(setsockopt(sockListen,SOL_SOCKET,SO_REUSEADDR,(const char *)&nReuseAddr,sizeof(int)) != 0)
    {
        cout<<"setsockopt错误"<<endl;
        goto theend;
    }
    addrLocal.sin_family = AF_INET;
    addrLocal.sin_addr.s_addr = htonl(INADDR_ANY);
    addrLocal.sin_port = htons(9090);
    if(bind(sockListen,(struct sockaddr *)&addrLocal,sizeof(sockaddr_in)) != 0)
    {
        cout<<"bind错误"<<endl;
        int n = WSAGetLastError();
        goto theend;
    }
    //准备监听
    cout<<"准备监听"<<endl;
    if(listen(sockListen,5)!=0)
    {
        cout<<"listen错误"<<endl;
        goto theend;
    }
    while(true)
    {
        //接收用户连接,被和完成端口关联
        sockAccept = WSAAccept(sockListen,NULL,NULL,NULL,0);
        perHandleData = (LPPER_HANDLE_DATA)malloc(sizeof(PER_HANDLE_DATA));
        if(perHandleData == NULL)
            continue;
        cout<<"socket number "<<sockAccept<<"接入"<<endl;
        perHandleData->sock = sockAccept;

        ioperdata = (LPPER_IO_OPERATION_DATA)malloc(sizeof(PER_IO_OPERATION_DATA));
        memset(&(ioperdata->Overlapped),0,sizeof(OVERLAPPED));
        (ioperdata->DataBuff[0]).len = 24;
        (ioperdata->DataBuff[0]).buf = ioperdata->Buff;
        ioperdata->OperationType = RECV_POSTED;
        if( ioperdata == NULL)
        {
            free(perHandleData);
            continue;
        }
        //关联
        cout<<"关联SOCKET和完成端口"<<endl;
        if(CreateIoCompletionPort((HANDLE)sockAccept,hCompletionPort,(DWORD)perHandleData,1) == NULL)
        {
            cout<<sockAccept<<"createiocompletionport错误"<<endl;
            free(perHandleData);
            free(ioperdata);
            continue;
        }
        //投递接收操作
        cout<<"投递接收操作"<<endl;
        WSARecv(perHandleData->sock,ioperdata->DataBuff,1,&dwRecvBytes,&dwFlags,&(ioperdata->Overlapped),NULL);
    }
theend:
    getchar();
    return 0;
}
//---------------------------------------------------------------------------
int Init()
{
    WSAData wsaData;
    if(WSAStartup(MAKEWORD(2,2),&wsaData) != 0)
    {
        cout<<"WSAStartup失败"<<endl;
        return -1;
    }

    if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
    {
        cout<<"SOCKET版本不对"<<endl;
        WSACleanup();
        return -1;
    }
    return 0;
}

DWORD WINAPI ServerWorkerThread(LPVOID CompletionPort)
{
    HANDLE ComPort = (HANDLE)CompletionPort;
    DWORD BytesTransferred;
    LPOVERLAPPED Overlapped;
    LPPER_HANDLE_DATA PerHandleData;
    LPPER_IO_OPERATION_DATA PerIoData;
    DWORD SendBytes,RecvBytes;
    DWORD Flags;
    BOOL bT;

    while(TRUE)
    {
        //等待完成端口上SOCKET的完成
        cout<<"等待完成端口上SOCKET的完成"<<endl;
        bT = GetQueuedCompletionStatus(ComPort,
            &BytesTransferred,(LPDWORD)&PerHandleData,
            (LPOVERLAPPED *)&PerIoData,INFINITE);

        //检查是否有错误产生
        if(BytesTransferred == 0 &&
            (PerIoData->OperationType == RECV_POSTED ||
            PerIoData->OperationType == SEND_POSTED))
        {
            //关闭SOCKET
            cout<<PerHandleData->sock<<"SOCKET关闭"<<endl;
            closesocket(PerHandleData->sock);
            free(PerHandleData);
            free(PerIoData);
            continue;
        }

        //为请求服务
        
        if(PerIoData->OperationType == RECV_POSTED)
        {
            //处理
            cout<<"接收处理"<<endl;
            cout<<PerHandleData->sock<<"SOCKET :"<<PerIoData->Buff<<endl;
            //回应客户端
            ZeroMemory(PerIoData->Buff,24);
            strcpy(PerIoData->Buff,"OK");
            Flags = 0;
            ZeroMemory((LPVOID)&(PerIoData->Overlapped),sizeof(OVERLAPPED));
            PerIoData->DataBuff[0].len = 2;
            PerIoData->DataBuff[0].buf = PerIoData->Buff;
            PerIoData->OperationType = SEND_POSTED;
            WSASend(PerHandleData->sock,PerIoData->DataBuff,
                1,&SendBytes,0,&(PerIoData->Overlapped),NULL);
        }
        else //if(PerIoData->OperationType == SEND_POSTED)
        {
            //发送时的处理
            cout<<"发送处理"<<endl;
            Flags = 0;
            ZeroMemory((LPVOID)&(PerIoData->Overlapped),sizeof(OVERLAPPED));
            ZeroMemory(PerIoData->Buff,24);
            PerIoData->DataBuff[0].len = 24;
            PerIoData->DataBuff[0].buf = PerIoData->Buff;
            PerIoData->OperationType = RECV_POSTED;
            WSARecv(PerHandleData->sock,PerIoData->DataBuff,
                1,&RecvBytes,&Flags,&(PerIoData->Overlapped),NULL);
        }
    }
}
*/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值