完成端口模型程序设计.docx
《完成端口模型程序设计.docx》由会员分享,可在线阅读,更多相关《完成端口模型程序设计.docx(10页珍藏版)》请在冰豆网上搜索。
完成端口模型程序设计
完成端口模型程序设计
1.实验目的
通过本次实验,掌握Windows socket的IO完成端口(IOCP)模型开发,利用编程能力,编写程序,利用服务线程,查看I/O操作的结果信息。
深入了解相关知识。
2.实验任务
首先查阅与完成端口模型程序设计的相关资料与技术指导,粗略制定实验的流程步骤,然后绘制程序设计的流程图,按照预先设计的流程图,进行程序的编写,在与同学老师的交流合作之下,进行程序的调试与修改,最后进行总结,记录调试结果,撰写相关实验报告
3.实验设计方案
①查阅技术相关资料
②绘制程序流程图
③按照以下步骤编写程序与调试
1:
创建完成端口
2:
将套接字与完成端口关联。
3:
调用输入输出函数,发起重叠IO操作。
4:
在服务线程中,等待完成端口重叠IO操作结果。
④总结体会与改进意见
⑤撰写实验报告
4.算法,流程图及关键代码说明
1.技术说明
I/O完成端口是一种内核对象。
利用完成端口,套接字应用程序能够管理数百上千个套接字。
应用程序创建完成端口对象后,通过指定一定数量的服务线程,为已经完成的重叠IO操作提供服务。
该模型可以达到最后的系统性能。
完成端口是一种真正意义上的异步模型。
在重叠I/O模型中,当Windows socket应用程序在调用WSARecv函数后立即返回,线程继续运行。
另一线程在在完成端口等待操作结果,当系统接收数据完成后,会向完成端口发送通知,然后应用程序对数据进行处理。
为了将Windows打造成一个出色的服务器环境,Microsoft开发出了IO完成端口。
它需要与线程池配合使用。
服务器有两种线程模型:
串行和并发模型。
串行模型:
单个线程等待客户端请求。
当请求到来时,该线程被唤醒来处理请求。
但是当多个客户端同时向服务器发出请求时,这些请求必须依次被请求。
并发模型:
单个线程等待请求到来。
当请求到来时,会创建新线程来处理。
但是随着更多的请求到来必须创建更多的线程。
这会导致系统内核进行上下文切换花费更多的时间。
线程无法即时响应客户请求。
伴随着不断有客户端请求、退出,系统会不断新建和销毁线程,这同样会增加系统开销。
而IO完成端口却可以很好的解决以上问题。
它的目标就是实现高效服务器程序。
与重叠IO相比较
重叠IO与IO完成端口模型都是异步模型。
都可以改善程序性能。
但是它们也有以下区别:
1:
在重叠IO使用事件通知时,WSAWaitForMultipleEvents只能等待WSA_MAXIMUM_WAIT_EVENTS(64)个事件。
这限制了服务器提供服务的客户端的数量。
2:
事件对象、套接字和WSAOVERLAPPED结构必须一一对应关系,如果出现一点疏漏将会导致严重的后果。
1:
创建IO完成端口
2:
将套接字与IO完成端口关联CreateIoCompletionPort(sListenSocket,hIOPort,完成键,0);
调用此函数即告诉系统:
当IO操作完成时,想完成端口发送一个IO操作完成通知。
这些通知按照FIFO 方式在完成队列中等待服务线程读取。
在利用IO完成端口开发套接字应用程序时,通常声明一个结构体保存与套接字相关的信息。
该结构通常作为完成键传递给CreateIoCompletionPort用以区分与套接字相关的信息。
我们可以给完成键传入任何对我们有用的信息,一般情况下都是传入一个结构的地址。
3:
发起重叠IO操作
将套接字与IO完成端口关联后,应用程序可以调用以下函数,发起重叠IO操作:
WSASend和WSASendTo:
发送数据。
WSARecv和WSARecvFrom:
接收数据。
在应用程序中通常声明一个和IO操作相关的结构体,它是WSAOVERLAPPED结构的扩展。
用以保存每一次IO操作的相关信息。
4:
等待重叠IO操作结果:
服务线程启动后,调用GetQueuedCompletionStatus函数等待重叠IO操作的完成结果。
当重叠IO操作完成时,IO操作完成通知被发送到完成端口上,此时函数返回。
综上,在使用完成端口开发Windows socket应用程序时,一般需要定义两种数据结构:
完成键和扩展的WSAOVERLAPPED结构。
完成键保存与套接字有关的信息。
在GetQueuedCompletionStatus返回时可以通过该参数获取套接字的相关信息。
这用于区分不同设备。
扩展的WSAOVERLAPPED结构,保存每次发起IO操作时IO操作相关的信息。
当GetQueuedCompletionStatus返回时通过该参数获取套接字的IO操作相关信息。
5:
取消异步操作。
当关闭套接字时,如果此时系统还有未完成的异步操作,应用程序可以调用CancelIo函数取消等待执行的异步操作。
2.流程图
3.关键代码及说明
///////////////////////////////////////////
//EventSelectServer.cpp文件
#include"../common/initsock.h"
#include
#include
#include"EventSelectServer.h"
//初始化Winsock库
CInitSocktheSock;
intmain()
{
USHORTnPort=4567;//此服务器监听的端口号
//创建监听套节字
SOCKETsListen=:
:
socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
sockaddr_insin;
sin.sin_family=AF_INET;
sin.sin_port=htons(nPort);
sin.sin_addr.S_un.S_addr=INADDR_ANY;
if(:
:
bind(sListen,(sockaddr*)&sin,sizeof(sin))==SOCKET_ERROR)
{
printf("Failedbind()\n");
return-1;
}
:
:
listen(sListen,200);
//创建事件对象,并关联到监听的套节字
WSAEVENTevent=:
:
WSACreateEvent();
:
:
WSAEventSelect(sListen,event,FD_ACCEPT|FD_CLOSE);
:
:
InitializeCriticalSection(&g_cs);
//处理客户连接请求,打印状态信息
while(TRUE)
{
intnRet=:
:
WaitForSingleObject(event,5*1000);
if(nRet==WAIT_FAILED)
{
printf("FailedWaitForSingleObject()\n");
break;
}
elseif(nRet==WSA_WAIT_TIMEOUT)//定时显式状态信息
{
printf("\n");
printf("TatolConnections:
%d\n",g_nTatolConnections);
printf("CurrentConnections:
%d\n",g_nCurrentConnections);
continue;
}
else//有新的连接未决
{
:
:
ResetEvent(event);
//循环处理所有未决的连接请求
while(TRUE)
{
sockaddr_insi;
intnLen=sizeof(si);
SOCKETsNew=:
:
accept(sListen,(sockaddr*)&si,&nLen);
if(sNew==SOCKET_ERROR)
break;
PSOCKET_OBJpSocket=GetSocketObj(sNew);
pSocket->addrRemote=si;
:
:
WSAEventSelect(pSocket->s,pSocket->event,FD_READ|FD_CLOSE|FD_WRITE);
AssignToFreeThread(pSocket);
}
}
}
:
:
DeleteCriticalSection(&g_cs);
return0;
}
//////////////////////////////////////////////////////////
//initsock.h文件
#include
#pragmacomment(lib,"WS2_32")//链接到WS2_32.lib
classCInitSock
{
public:
CInitSock(BYTEminorVer=2,BYTEmajorVer=2)
{
//初始化WS2_32.dll
WSADATAwsaData;
WORDsockVersion=MAKEWORD(minorVer,majorVer);
if(:
:
WSAStartup(sockVersion,&wsaData)!
=0)
{
exit(0);
}
}
~CInitSock()
{
:
:
WSACleanup();
}
};
5.调试结果
结果一:
开启EventSelectServer,会看到,当前连接,与总连接数量都为0
结果二:
开启一个Client(客户端)
结果三:
开启客户端之后,再查看服务器端,会发现,当前连接数量与总连接数量都发生了改变,此时都为1,符合实情。
结果四:
开启2个客户端即
关闭一个客户端
关闭所有客户端
6.改进意见与心得体会
通过此次实验,我们掌握了Windows socket的IO完成端口(IOCP)模型开发,利用编程能力,编写程序,利用服务线程,查看I/O操作的结果信息。
深入了解相关知识。
重叠IO与IO完成端口模型都是异步模型。
都可以改善程序性能。
但是它们也有以下区别:
在重叠IO使用事件通知WSAWaitForMultipleEvents只能等待WSA_MAXIMUM_WAIT_EVENTS(64)个事件。
这限制了服务器提供服务的客户端的数量。
事件对象、套接字和WSAOVERLAPPED结构必须一一对应关系,如果出现一点疏漏将会导致严重的后果。
本次实验中,我们通过一步步的实验,调试,发现问题,查找资料,发现错误,调试改进,直到最后完成整个实验,从实验中巩固学习到的知识,并将它适当运用,达成目标。
在老师的细心指导下,与同学的配合联机调试下,此次实验,圆满完成,收益良多。
7.主要参考资料
《网络应用与开发》