`
wx1569567608
  • 浏览: 71248 次
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

IOCP简单模型

 
阅读更多

// dfgasd.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"


#include   <winsock2.h>  
//#include   <windows.h>  
#include   <stdio.h>  
#pragma comment(lib,"ws2_32.lib")

#define   PORT   5150  
#define   DATA_BUFSIZE   8192  

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   WINAPI   ServerWorkerThread(LPVOID   CompletionPortID);  

int main(void)  
{  
 SOCKADDR_IN   InternetAddr;  
 SOCKET   Listen;  
 SOCKET   Accept;  
 HANDLE   CompletionPort;  
 SYSTEM_INFO   SystemInfo;  
 LPPER_HANDLE_DATA   PerHandleData;  
 LPPER_IO_OPERATION_DATA   PerIoData;  
 int   i;  
 DWORD   RecvBytes;  
 DWORD   Flags;  
 DWORD   ThreadID;  
 WSADATA   wsaData;  
 DWORD   Ret;  
   
 if   ((Ret   =   WSAStartup(0x0202,   &wsaData))   !=   0)  
 {  
  printf("WSAStartup失败了,错误信息如下:   %d\n",   Ret);  
  return;  
 }  
   
 // 设置一个I/O完成端口.  
   
 if   ((CompletionPort   =   CreateIoCompletionPort(INVALID_HANDLE_VALUE,   NULL,   0,   0))   ==   NULL)  
 {  
  printf(   "CreateIoCompletionPort 失败了,错误信息如下:   %d\n",   GetLastError());  
  return;  
 }  
   
 // 测试系统中有多少cpu处理器
   
 GetSystemInfo(&SystemInfo);  
   
 //   基于系统可用的处理器创建工作线程,为每个处理器创建连个线程  
   
 for(i   =   0;   i   <   SystemInfo.dwNumberOfProcessors   *   2;   i++)  
 {  
  HANDLE   ThreadHandle;  
  
  // 创建一个服务端线程并且传递一个完成端口给这个线程.  
  
  if   ((ThreadHandle   =   CreateThread(NULL,   0,   ServerWorkerThread,   CompletionPort,  
   0,   &ThreadID))   ==   NULL)  
  {  
   printf("CreateThread()发生了如下错误: %d\n",   GetLastError());  
   return;  
  }  
  else
  {printf("创建了一个完成端口.\n");
  }
  //   关闭 thread句柄
  CloseHandle(ThreadHandle);  
 }  
   
 //   创建一个监听套接字
   
 if   ((Listen   =WSASocket(AF_INET,   SOCK_STREAM,   0,   NULL,0,WSA_FLAG_OVERLAPPED))   ==   INVALID_SOCKET)  
 {  
  printf("WSASocket() 发生了如下错误: %d\n",   WSAGetLastError());  
  return;  
 }
 else    
 {printf("创建监听套接字成功\n");}
 InternetAddr.sin_family   =   AF_INET;  
 InternetAddr.sin_addr.s_addr   =   htonl(INADDR_ANY);  
 InternetAddr.sin_port   =   htons(PORT);  
   
 if   (bind(Listen,   (PSOCKADDR)   &InternetAddr,   sizeof(InternetAddr))   ==   SOCKET_ERROR)  
 {  
  printf("bind()端口或IP时发生了如下错误: %d\n",   WSAGetLastError());  
  return;  
 }  
 else
 {printf("绑定端口%d成功\n",PORT);}
 // 准备socket 用来监听  
   
 if   (listen(Listen,   5)   ==   SOCKET_ERROR)  
 {  
  printf("listen() 发生了如下错误   %d\n",   WSAGetLastError());  
  return;  
 }  
 else
 {printf("预处理成功,开始在端口 %d 处监听...\n",PORT);}
 //接受连接并且交给完成端口处理
   
 while(TRUE)  
 {  
  if   ((Accept   =   WSAAccept(Listen,   NULL,   NULL,   NULL,   0))   ==   SOCKET_ERROR)  
  {  
   printf("WSAAccept()   发生了如下错误:   %d\n",   WSAGetLastError());  
   return;  
  }  
  
  // 创建一个套接字信息结构体去联系起来socket  
  if   ((PerHandleData   =   (LPPER_HANDLE_DATA)   GlobalAlloc(GPTR,    
   sizeof(PER_HANDLE_DATA)))   ==   NULL)  
  {  
   printf("GlobalAlloc()   发生了如下错误:   %d\n",   GetLastError());  
   return;  
  }  
  
  // 将接受到的套接字与原始的完成端口联系起来.  
  
  printf("号码为   %d   的socket连接上了\n",   Accept);  
  PerHandleData->Socket   =   Accept;  
  
  if   (CreateIoCompletionPort((HANDLE)   Accept,   CompletionPort,   (DWORD)   PerHandleData,  
   0)   ==   NULL)  
  {  
   printf("CreateIoCompletionPort   发生了如下错误:   %d\n",   GetLastError());  
   return;  
  }  
  
  //   创建每一个I/O 套接字信息结构体去和下面被调用的 to   associate   with   the    
  //   WSARecv 连接.  
  
  if   ((PerIoData   =   (LPPER_IO_OPERATION_DATA)   GlobalAlloc(GPTR,                     sizeof(PER_IO_OPERATION_DATA)))   ==   NULL)  
  {  
   printf("GlobalAlloc() 发生了如下错误: %d\n",   GetLastError());  
   return;  
  }  
  else{printf("接收了一个连接\n");}
  ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));  
  PerIoData->BytesSEND   =   0;  
  PerIoData->BytesRECV   =   0;  
  PerIoData->DataBuf.len   =   DATA_BUFSIZE;  
  PerIoData->DataBuf.buf   =   PerIoData->Buffer;  
  
  Flags   =   0;  
  if   (WSARecv(Accept,   &(PerIoData->DataBuf),   1,   &RecvBytes,   &Flags,  
   &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)  
  {  
   if   (WSAGetLastError()   !=   ERROR_IO_PENDING)  
   {  
    printf("WSARecv() 发生了如下错误: %d\n",   WSAGetLastError());  
    return;  
   }  
  }  
 }  
}  

DWORD   WINAPI   ServerWorkerThread(LPVOID   CompletionPortID)  
{  
 HANDLE   CompletionPort   =   (HANDLE)   CompletionPortID;  
 DWORD   BytesTransferred;  
 LPOVERLAPPED   Overlapped;  
 LPPER_HANDLE_DATA   PerHandleData;  
 LPPER_IO_OPERATION_DATA   PerIoData;  
 DWORD   SendBytes,   RecvBytes;  
 DWORD   Flags;  
 
 while(TRUE)  
 {  
  
  if   (GetQueuedCompletionStatus(CompletionPort,   &BytesTransferred,  
   (LPDWORD)&PerHandleData,   (LPOVERLAPPED   *)   &PerIoData,   INFINITE)   ==   0)  
  {  
   printf("GetQueuedCompletionStatus   发生了如下错误: %d\n",   GetLastError());  
   return   0;  
  }  
  
  //首先检查一下去套接字看是否在上发生了错误并且如果发生了错误就关闭套接
  //字并且清除与套接字连接的 SOCKET_INFORMATION结构信息体
  if   (BytesTransferred   ==   0)  
  {  
   printf("正在关闭socket   %d\n",   PerHandleData->Socket);  
   
   if   (closesocket(PerHandleData->Socket)   ==   SOCKET_ERROR)  
   {  
    printf("closesocket()   发生了如下错误: %d\n",   WSAGetLastError());  
    return   0;  
   }  
   
   GlobalFree(PerHandleData);  
   GlobalFree(PerIoData);  
   continue;  
  }  
  //检查如果 BytesRECV字段等于0,这就意味着一个 WSARecv调用刚刚完成了所以从完成的WSARecv()调用中
  //用BytesTransferred值更新 BytesRECV字段
  if   (PerIoData->BytesRECV   ==   0)  
  {  
   PerIoData->BytesRECV   =   BytesTransferred;  
   PerIoData->BytesSEND   =   0;  
  }  
  else  
  {  
   PerIoData->BytesSEND   +=   BytesTransferred;  
  }  
  
  if   (PerIoData->BytesRECV   >   PerIoData->BytesSEND)  
  {  
   //发布另外一个 WSASend()请求
   //既然WSASend()不是 gauranteed去发送所有字节的请求
   //继续调用 WSASend()发送直到所有收到的字节被发送
   
   ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));  
   
   PerIoData->DataBuf.buf   =   PerIoData->Buffer   +   PerIoData->BytesSEND;  
   PerIoData->DataBuf.len   =   PerIoData->BytesRECV   -   PerIoData->BytesSEND;  
   
   if   (WSASend(PerHandleData->Socket,   &(PerIoData->DataBuf),   1,   &SendBytes,   0,  
    &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)  
   {  
    if   (WSAGetLastError()   !=   ERROR_IO_PENDING)  
    {  
     printf("WSASend() 发生了如下错误:   %d\n",   WSAGetLastError());  
     return   0;  
    }  
   }  
  }  
  else  
  {  
   PerIoData->BytesRECV   =   0;  
   //现在没有更多的字节发送过去用来post另外一个WSARecv()请求
   
   Flags   =   0;  
   ZeroMemory(&(PerIoData->Overlapped),   sizeof(OVERLAPPED));  
   
   PerIoData->DataBuf.len   =   DATA_BUFSIZE;  
   PerIoData->DataBuf.buf   =   PerIoData->Buffer;  
   
   if   (WSARecv(PerHandleData->Socket,   &(PerIoData->DataBuf),   1,   &RecvBytes,   &Flags,  
    &(PerIoData->Overlapped),   NULL)   ==   SOCKET_ERROR)  
   {  
    if   (WSAGetLastError()   !=   ERROR_IO_PENDING)  
    {  
     printf("WSARecv() 发生了如下错误:   %d\n",   WSAGetLastError());  
     return   0;  
    }  
   }  
  }  
 }  

 

转载于:https://my.oschina.net/u/158055/blog/694476

分享到:
评论

相关推荐

    C# IOCP完成端口模型(简单实用高效)

    在.NET编程环境中,C# IOCP(完成端口,I/O Completion Ports)是一种高级的并发I/O模型,常用于构建高性能的服务器应用。IOCP模型是Windows操作系统提供的一种高效的异步I/O机制,它能够充分利用多核处理器的优势,...

    一个简单的IOCP模型的服务器

    本项目提供了一个简单的IOCP模型服务器的实现,旨在帮助开发者理解和掌握IOCP的基本原理和使用方法。** 在IOCP模型中,服务器的核心是IOCP对象,它负责管理和协调所有I/O操作的完成。当一个I/O操作完成后,系统会将...

    简单iocp模型例子

    下面将详细介绍IOCP模型及其工作原理,以及如何创建和使用一个简单的IOCP服务器。** ### IOCP模型概述 IOCP(I/O Completion Port)是Windows系统提供的多线程I/O调度机制,它允许应用程序通过单一的端口处理多个...

    简单IOCPserver模型

    "简单IOCPserver模型"结合了IOCP的高性能网络处理能力和RichEdit的富文本展示功能,为开发人员提供了一个基础的、可扩展的服务器框架。通过理解IOCP的工作原理和使用方法,以及如何集成RichEdit控件,我们可以构建出...

    IOCP 完成端口模型简单封装

    《IOCP完成端口模型简单封装详解》 IOCP(完成端口,英文名I/O Completion Ports)是一种在Windows操作系统中实现高并发网络通信的重要机制。它为高性能服务器设计提供了强大的支持,尤其适用于处理大量并发连接...

    IOCP 模型学习总结代码

    在"IOCP模型测试代码"中,可能包含了一个简单的服务器示例,它创建IOCP,接收客户端连接,发起异步读写操作,并使用工作线程处理完成的I/O事件。Readme.txt文件应详细解释了代码结构、关键函数以及如何运行和测试...

    winsock网络通信(select和IOCP模型,客户端和服务器都有)

    在客户端和服务器的网络通信中,select模型常用于简单和低并发的场景,例如小型聊天应用或个人服务器。而IOCP模型则更适合大型的、高并发的服务,如Web服务器、游戏服务器或大数据流传输应用。 为了实现这些模型,...

    Delphi IOCP简单实例

    标题中的“Delphi IOCP简单实例”指的是使用Delphi编程语言实现的一个基于I/O完成端口(IOCP,Input/Output Completion Port)的简单示例。IOCP是Windows操作系统提供的一种高效率、高性能的异步I/O模型,常用于网络...

    C#下IOCP简单例子.rar

    标题"C#下IOCP简单例子.rar"表明这是一个关于使用C#编程语言实现IO完成端口(IOCP,Input/Output Completion Port)技术的示例项目。IOCP是Windows操作系统中用于提高网络I/O性能的一种机制,尤其适用于高并发的...

    iocp简单例子,对初学者非常有利

    标题中的"IOCP"指的是Windows操作系统中的"Input/Output Completion Ports"(输入/输出完成端口),这是一种高效率、多线程的I/O模型,特别适用于处理大量并发连接的网络服务器。IOCPort允许应用程序将I/O操作异步化...

    实现了IOCP完成端口模型的服务器设计

    IOCP是基于事件驱动的,当I/O操作完成时,系统会将控制权交还给等待该事件的线程,而不是简单地唤醒线程,这样可以避免线程上下文切换的开销。IOCP允许一个线程处理多个已完成的I/O操作,显著提高了系统的并发能力。...

    C#下的IOCP的简单实现

    本文将详细介绍如何在C#下实现一个简单的IOCP模型。 首先,理解IOCP的基本原理至关重要。IOCP通过将I/O操作异步化,允许线程在等待I/O完成时被重新分配到其他任务,而不是阻塞在某个特定的I/O操作上。当I/O操作完成...

    IOCP基本原理

    但理解和实现IOCP编程并不简单,需要深入理解Windows内核I/O机制以及线程池的运作原理。开发者必须谨慎地设计线程池大小、工作队列策略等,以确保系统在各种负载情况下都能保持稳定和高效。 总之,IOCP是Windows...

    一个关于IOCP的简单DEMO

    "一个关于IOCP的简单DEMO" 这个标题表明这是一个演示性的程序,主要展示了如何使用I/O完成端口(IOCP,Input/Output Completion Port)技术。IOCP是Windows操作系统中的一种高效率的网络编程模型,用于处理大量并发...

    一个简单的IOCP服务器/客户端类

    **IOCP(I/O完成端口)**是Windows操作系统中的一种高效、多线程I/O模型,主要用于处理大量并发的网络连接。IOCP利用操作系统的内核态完成数据传输,从而减少用户态与内核态之间的上下文切换,提高系统性能。在本...

    IOCP.rar_IOCP_delphi iocp_iocp csdn_iocp delphi

    IOCP是Windows操作系统提供的一种高度优化的异步I/O模型,常用于构建高性能的网络服务器,如TCP或UDP服务器。 描述中提到这是在网上找到的IOCP相关资料,目的是为从事这方面工作的人提供帮助。这些资料可能包含了...

    iocp开发一个最简单的例子

    在Windows操作系统中,I/O完成端口(I/O Completion Ports,简称IOCP)是一种高效的多线程I/O模型,尤其适用于处理大量的并发I/O请求。本篇文章将通过一个最简单的IOCP示例,深入探讨其工作原理和使用方法。 首先,...

    socket中wsaeventselect,iocp

    总结来说,WSAAsyncSelect适用于简单窗口应用,WSAEventSelect适合处理多个套接字但不超过64个事件的情况,而IOCP则是高性能服务器应用的理想选择。开发者需要根据项目需求和资源限制,选择合适的I/O模型。

    windows iocp网络通讯库封装

    总结来说,"windows iocp网络通讯库封装"是一个利用Windows IOCP技术构建的C++网络通信库,它通过`ITcpClient`和`ITcpServer`接口为开发者提供了简单易用的客户端和服务器端功能,同时借助`libsocket.dll`和`...

Global site tag (gtag.js) - Google Analytics