`
deepfuture
  • 浏览: 4321410 次
  • 性别: Icon_minigender_1
  • 来自: 湛江
博客专栏
073ec2a9-85b7-3ebf-a3bb-c6361e6c6f64
SQLite源码剖析
浏览量:79303
1591c4b8-62f1-3d3e-9551-25c77465da96
WIN32汇编语言学习应用...
浏览量:68105
F5390db6-59dd-338f-ba18-4e93943ff06a
神奇的perl
浏览量:101194
Dac44363-8a80-3836-99aa-f7b7780fa6e2
lucene等搜索引擎解析...
浏览量:280268
Ec49a563-4109-3c69-9c83-8f6d068ba113
深入lucene3.5源码...
浏览量:14535
9b99bfc2-19c2-3346-9100-7f8879c731ce
VB.NET并行与分布式编...
浏览量:65154
B1db2af3-06b3-35bb-ac08-59ff2d1324b4
silverlight 5...
浏览量:31187
4a56b548-ab3d-35af-a984-e0781d142c23
算法下午茶系列
浏览量:45071
社区版块
存档分类
最新评论

WIN网络编程-IOCP与可伸缩网络程序

阅读更多

/////////////////////////////////////////////////
//IOCPDemo.cpp文件调试通过

//I/O完成端口最初的设计是应用程序发出一些异步I/O请求,当这些请求完

//成时,设备驱动把这些工作排序到完成端口,在完成端口等待的线程池

//可以处理这些完成I/O。

//首先调用CreateCompletionPort创建一个完成端口对象。函数的两个功能如下:

//1、创建一个完成端口对象。

//2、将一个或者多个文件句柄(此处是套节字)关联到I/O完成端口对象。

//最初创建时,需要设置的参数是NUMBEROFCONCURRENTTHREADS,它定义了允

//许在完成端口上同时执行的线程的数量。为0表示允许线程数量与处理器数

//量一样多。

//CreateIoCompletionPort函数的NumberOfConcurrentThreads参数个线程允

//许运行,即使创建了比允许线程更多的工作线程,仍只有允许线程数进

//入线程池。但是有时候,确实需要创建更多的线程,因为某个

//线程调用了一个函数,进行了暂停状态,体眠后暂时不能为线程池所有。所以

//必须有新的工作线程来补充。

//有了足够的线程来处理完成端口上的I/O请求之后,就该为完成端口关联套

//节字句柄,向完成端口关联套节字句柄之后,便可以通过在套节字上投递重叠

//发送和接收请求处理I/O,在这些I/O操作完成时,I/O系统会向完成端口对

//象发送一个完成通知封包。应用程序使用GetQueuedCompletionStatus函数

//可以取得这些队列中的封包,返回后说明发生了如下事件之一:

//1、GetQueuedCompletionStatus调用失败,说明在此套节字上有错误发生。

//2、BytesTransferred为0说明套节字被对方关闭。

//3、I/O请求成功完成。通过per-I/O数据中的OperationType域查看哪个I/O

//请求完成了。

//在每个套节字句柄关闭,通过PostQueuedCompletionStatus向工作线程发

//送特定的完成封包终止完成端口上处理的I/O线程,


#include "../common/initsock.h"
#include <stdio.h>
#include <windows.h>

// 初始化Winsock库
CInitSock theSock;

#define BUFFER_SIZE 1024

typedef struct_PER_HANDLE_DATA//per-handle数据
{
SOCKETs;//对应的套节字句柄
sockaddr_in addr;// 客户方地址
} PER_HANDLE_DATA, *PPER_HANDLE_DATA;


typedef struct_PER_IO_DATA//per-I/O数据
{
OVERLAPPEDol;//重叠结构
char buf[BUFFER_SIZE];//数据缓冲区
intnOperationType;// 操作类型
#define OP_READ 1
#define OP_WRITE 2
#define OP_ACCEPT 3
} PER_IO_DATA, *PPER_IO_DATA;


DWORD WINAPI ServerThread(LPVOID lpParam)
{
// 得到完成端口对象句柄
HANDLE hCompletion = (HANDLE)lpParam;

DWORD dwTrans;
PPER_HANDLE_DATA pPerHandle;
PPER_IO_DATA pPerIO;
while(TRUE)
{
//在关联到此完成端口的所有套节字上等待I/O完成
BOOL bOK =::GetQueuedCompletionStatus(hCompletion,
&dwTrans,(LPDWORD)&pPerHandle,(LPOVERLAPPED*)&pPerIO, WSA_INFINITE);
if(!bOK)//在此套节字上有错误发生
{
::closesocket(pPerHandle->s);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}

if(dwTrans == 0&&//套节字被对方关闭
(pPerIO->nOperationType== OP_READ || pPerIO->nOperationType ==OP_WRITE))

{
::closesocket(pPerHandle->s);
::GlobalFree(pPerHandle);
::GlobalFree(pPerIO);
continue;
}

switch(pPerIO->nOperationType)//通过per-I/O数据中的nOperationType域查看什么I/O请求完成了
{
caseOP_READ:// 完成一个接收请求
{
pPerIO->buf[dwTrans]= '\0';
printf(pPerIO-> buf);

//继续投递接收I/O请求
WSABUFbuf;
buf.buf= pPerIO->buf ;
buf.len= BUFFER_SIZE;
pPerIO->nOperationType= OP_READ;

DWORDnFlags = 0;
::WSARecv(pPerHandle->s,&buf, 1, &dwTrans,&nFlags,&pPerIO->ol, NULL);
}
break;
case OP_WRITE: //本例中没有投递这些类型的I/O请求
case OP_ACCEPT:
break;
}
}
return 0;
}


void main()
{
int nPort = 4567;
//创建完成端口对象,创建工作线程处理完成端口对象中事件

//参数说明:

//

//HANDLE WINAPI CreateIoCompletionPort(//  __in      HANDLE FileHandle,要关联的套节字句柄//  __in_opt  HANDLE ExistingCompletionPort,
//上面创建的完成端口对象句柄//  __in      ULONG_PTR CompletionKey,
//一个句柄惟一数据,它将与FILEHANDLE套节字句柄关联在一起。
//可在此存储任意类型的信息。//  __in      DWORD NumberOfConcurrentThreads//);


HANDLE hCompletion =::CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);

//在此只创建了一个完成端口对象
::CreateThread(NULL, 0, ServerThread,(LPVOID)hCompletion, 0, 0);

// 创建监听套节字,绑定到本地地址,开始监听
SOCKET sListen = ::socket(AF_INET, SOCK_STREAM,0);
SOCKADDR_IN si;
si.sin_family = AF_INET;
si.sin_port = ::ntohs(nPort);
si.sin_addr.S_un.S_addr = INADDR_ANY;
::bind(sListen, (sockaddr*)&si,sizeof(si));
::listen(sListen, 5);

// 循环处理到来的连接
while(TRUE)
{
// 等待接受未决的连接请求
SOCKADDR_IN saRemote;
int nRemoteLen =sizeof(saRemote);

//创建新的接收套节字
SOCKET sNew = ::accept(sListen,(sockaddr*)&saRemote,&nRemoteLen);

//接受到新连接之后,为它创建一个per-handle数据,并将它们关联到完成端口对象。
PPER_HANDLE_DATA pPerHandle=
(PPER_HANDLE_DATA)::GlobalAlloc(GPTR,sizeof(PER_HANDLE_DATA));
pPerHandle->s =sNew;
memcpy(&pPerHandle->addr,&saRemote, nRemoteLen);

//多个套节字对应一个I/O完成对象
::CreateIoCompletionPort((HANDLE)pPerHandle->s,hCompletion, (DWORD)pPerHandle, 0);

// 投递一个接收请求
PPER_IO_DATA pPerIO =(PPER_IO_DATA)::GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
pPerIO->nOperationType= OP_READ;
WSABUF buf;
buf.buf =pPerIO->buf;
buf.len =BUFFER_SIZE;
DWORD dwRecv;
DWORD dwFlags = 0;
::WSARecv(pPerHandle->s,&buf, 1, &dwRecv,&dwFlags,&pPerIO->ol, NULL);
}
}

0
0
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics