【整理】重叠IO模型的编程思路及C++源代码
来源:互联网 发布:淘宝评价什么时候生效 编辑:程序博客网 时间:2024/05/17 08:19
编程步骤
1、创建一个套接字,开始在指定的端口上监听连接请求。
2、接收一个入站的连接请求。
3、为接受的套接字创建新的WSAOVERLAPPED结构,并分配事件对象句柄。
4、以WSAOVERLAPPED结构为参数,在套接字上投递WSARecv调用。
5、将所有接受套接字的事件组建事件数组,并调用WSAWaitForMultipleEvents函数,等待与重叠调用关联在一起的事件受信。
6、使用WSAGetOverlappedResult函数,判断重叠调用的返回状态。
7、重新组建事件数组。
8、在套接字上重投递WSARecv请求。
9、重复5~8。
SockObject.h
#include <winsock2.h>class SockObject{public:SOCKET m_sock;int m_operatNum;public:SockObject(void){};SockObject(SOCKET mySock);SockObject(SockObject &mySockObject);~SockObject(void){};};SockObject::SockObject(SOCKET mySock){m_sock = mySock;m_operatNum = 0;}SockObject::SockObject(SockObject &mySockObject){m_sock = mySockObject.m_sock;m_operatNum = mySockObject.m_operatNum;}
OverObject
OverObject.h
#include <winsock2.h>#include <iostream>using namespace std;/*******************************************************************************数据结构名称:OverObject*功能:记录一个套接字的一个操作、一个事件和一个重叠I/O的关联*****************************************************************************/class OverObject{public:SOCKET m_sock; /*绑定的套接字*/OVERLAPPED m_overlapped; /*绑定的重叠I/O*/char *m_buf; /*用于存放数据的缓冲区*/int m_len; /*缓冲区的长度*/int m_operation; /*套接字针对的操作*/public:bool operator==(const OverObject &myOverObject) const;public:OverObject(void);OverObject(const OverObject &myOverObject);OverObject(SOCKET mySock, int myLen);~OverObject(void);};/*定义指向重叠对象的指针类型*/typedef OverObject * PtrOverObject;OverObject::~OverObject(void){delete m_buf;}/********************************************************************************* 函数介绍:本函数是OverObject类的复制构造函数。*********************************************************************************/OverObject::OverObject(const OverObject &myOverObject){m_sock = myOverObject.m_sock; m_overlapped = myOverObject.m_overlapped;m_buf = new char[myOverObject.m_len];strcpy(m_buf,myOverObject.m_buf); m_len = myOverObject.m_len; m_operation = myOverObject.m_operation;}/********************************************************************************* 函数介绍:本函数是OverObject类带参数的构造函数。*********************************************************************************/OverObject::OverObject(SOCKET mySock, int myLen){m_sock = mySock;m_buf = new char[myLen];m_len = myLen;m_overlapped.hEvent = ::WSACreateEvent();}/********************************************************************************* 函数介绍:本函数是OverObject类的==运算符重载函数*********************************************************************************/bool OverObject::operator==(const OverObject &myOverObject) const{if(this->m_sock == myOverObject.m_sock && this->m_operation == myOverObject.m_operation && this->m_len == myOverObject.m_len && !strcmp(this->m_buf, myOverObject.m_buf)){ cout << "the two overObject is eque !" << endl;return true;}else{return false;}}
Overlapped
Overlapped.h
#include <winsock2.h>#include "OverObject.h"#include "SockObject.h"#include <list>#include <vector>using namespace std;/*******************************************************************************类名称:Overlapped*功能:记录系统中需要维护的所有重叠I/O*****************************************************************************/#define OP_ACCEPT 1#define OP_READ 2#define OP_WRITE 3 class Overlapped{public: list<OverObject> overObjects; /*需要维护的所有重叠I/O*/ vector<HANDLE> eventArray; /*所有重叠I/O所对应的事件组成的数组,作为等待函数的参数*/ vector<SockObject> sockArray; /*需要维护的所有套接字,当操作为零时关闭套接字*/public: list<OverObject>::iterator GetOverObject(SOCKET mySock, int myLen); void FreeOverObject(list<OverObject>::iterator myPtrOverObject); list<OverObject>::iterator Overlapped::FindOverObject(HANDLE myEvent); void RebuildEventArray(); void CreateAcceptEvent(); void SetAcceptEvent(); void ResetAcceptEvent(); bool IsAcceptEvent(int index); bool PostRecv(list<OverObject>::iterator myPtrOverObject); bool PostSend(list<OverObject>::iterator myPtrOverObject); bool PostAccept(list<OverObject>::iterator myPtrOverObject); Overlapped(void){};~Overlapped(void){}; void InitSocket();}; /********************************************************************************* 函数介绍:创建重叠对象的类对象,并插入重叠对象链表中。*********************************************************************************/list<OverObject>::iterator Overlapped::GetOverObject(SOCKET mySock, int myLen){ OverObject localOverObject(mySock, myLen); overObjects.push_back(localOverObject); eventArray.push_back(localOverObject.m_overlapped.hEvent); list<OverObject>::iterator ret = overObjects.end(); ret--; return ret; } /********************************************************************************* 函数介绍:释放重叠对象链表中指定的重叠对象。*********************************************************************************/void Overlapped::FreeOverObject(list<OverObject>::iterator myPtrOverObject){ overObjects.erase(myPtrOverObject);} /********************************************************************************* 函数介绍:从重叠对象列表中查找指定事件所对应的重叠对象。*********************************************************************************/list<OverObject>::iterator Overlapped::FindOverObject(HANDLE myEvent){ list<OverObject>::iterator localIerator; for(localIerator = overObjects.begin(); localIerator != overObjects.end(); localIerator++) { if(localIerator->m_overlapped.hEvent == myEvent) { break; } } return localIerator;} /********************************************************************************* 函数介绍:遍历重叠对象列表,重建重叠对象列表所对应的事件数组。*********************************************************************************/void Overlapped::RebuildEventArray(){ eventArray.clear(); list<OverObject>::iterator overObjIterator; overObjIterator = overObjects.begin(); for(overObjIterator; overObjIterator != overObjects.end(); ++overObjIterator) { eventArray.push_back(overObjIterator->m_overlapped.hEvent); }} /********************************************************************************* 函数介绍:投放接受操作,即将指定套接字的Recv操作与重叠I/O对象关联起来。*********************************************************************************/bool Overlapped::PostRecv(list<OverObject>::iterator myPtrOverObject){ myPtrOverObject->m_operation = OP_READ; DWORD dwBytes; DWORD dwFlags = 0; WSABUF buf; buf.buf = myPtrOverObject->m_buf; buf.len = myPtrOverObject->m_len; memset(buf.buf, 0, buf.len); if(::WSARecv(myPtrOverObject->m_sock, &buf, 1, &dwBytes, &dwFlags, &myPtrOverObject->m_overlapped,NULL)!=NO_ERROR) { if(::WSAGetLastError() != WSA_IO_PENDING) { return false; } } return true;} /********************************************************************************* 函数介绍:投放发送操作,即将指定套接字的Send操作与重叠I/O对象关联起来。*********************************************************************************/bool Overlapped::PostSend(list<OverObject>::iterator myPtrOverObject){ myPtrOverObject->m_operation = OP_WRITE; DWORD dwBytes; DWORD dwFlags = 0; WSABUF buf; buf.buf = myPtrOverObject->m_buf; buf.len = myPtrOverObject->m_len; if(::WSASend(myPtrOverObject->m_sock, &buf, 1, &dwBytes, dwFlags, &myPtrOverObject->m_overlapped,NULL)!=NO_ERROR) { if(::WSAGetLastError() != WSA_IO_PENDING) { return false; } } return true;} /********************************************************************************* 函数介绍:创建accept函数完成事件,用于处理accepe后等待函数的等待事件句柄数组发 生变化,若此时无事件触发,等待事件句柄数组仍以原来的事件句柄数组为依 据等待。*********************************************************************************/void Overlapped::CreateAcceptEvent(){ //标志套接字,用于触发accept完成事件。 SOCKET myClient = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED); list<OverObject>::iterator acceptIterator = GetOverObject(myClient, 512); RebuildEventArray();} /********************************************************************************* 函数介绍:当accept函数完成时,重置accept所对应的事件,从而使得等待函数能够在改 变后的事件句柄数组上等待。*********************************************************************************/void Overlapped::SetAcceptEvent(){ ::SetEvent(eventArray.front());} void Overlapped::ResetAcceptEvent(){ ::ResetEvent(eventArray.front());} bool Overlapped::IsAcceptEvent(int index){ if(index == 0) { return true; } else { return false; }}
主文件:
#include "Overlapped.h"#include <windows.h>#include <process.h>bool OperateFunction(PtrOverObject myPtrOverObject);UINT WINAPI ServerThread(PVOID pvParam);Overlapped myOverlapped;int main(){WSADATA wsaData;if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0){cout<<"failed to load winsock !"<<endl;exit(0);}SOCKET mylisten, myClient;mylisten = ::WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);struct sockaddr_in localAddr, clientAddr;localAddr.sin_family = AF_INET;localAddr.sin_port = ntohs(5500);localAddr.sin_addr.S_un.S_addr = inet_addr("59.73.161.221");bind(mylisten, (sockaddr*)&localAddr, sizeof(localAddr));listen(mylisten, 5);int sizeAddr = sizeof(clientAddr);cout << "server is listening......" << endl;myOverlapped.CreateAcceptEvent();int x;_beginthreadex(NULL, 0, ServerThread, &x, 0, NULL);/*循环接收客户端的连接,创建与客户端通信的重叠IO对象,并重建事件句柄数组*/while(true){myClient = accept(mylisten, (struct sockaddr*)&clientAddr, &sizeAddr);if(myClient==INVALID_SOCKET){cout<<"accept is failed !"<<endl;return -1;}list<OverObject>::iterator localIterator = myOverlapped.GetOverObject(myClient, 512);myOverlapped.PostRecv(localIterator);myOverlapped.RebuildEventArray();myOverlapped.SetAcceptEvent();}char ch;cin >> ch;return 0;}/********************************************************************************* 函数介绍:数据处理函数,按照不同操作类型,处理数据的发送或接受。*********************************************************************************/bool OperateFunction(list<OverObject>::iterator myOverObjectIterator){DWORD dwTrans;DWORD dwFlags;BOOL ret = ::WSAGetOverlappedResult(myOverObjectIterator->m_sock, &(myOverObjectIterator->m_overlapped), &dwTrans, false, &dwFlags);if(!ret){if(myOverObjectIterator->m_sock != INVALID_SOCKET){closesocket(myOverObjectIterator->m_sock);}cout << "socket error : " << ::GetLastError() << endl;myOverlapped.FreeOverObject(myOverObjectIterator);myOverlapped.RebuildEventArray();return false;}switch(myOverObjectIterator->m_operation){case OP_READ: /*接收数据完成*/if(dwTrans > 0){cout << myOverObjectIterator->m_buf << endl;list<OverObject>::iterator localIterator = myOverlapped.GetOverObject(myOverObjectIterator->m_sock, 512);localIterator->m_len = myOverObjectIterator->m_len;strcpy(localIterator->m_buf, myOverObjectIterator->m_buf);myOverlapped.PostSend(localIterator);myOverlapped.RebuildEventArray();return true;}else{closesocket(myOverObjectIterator->m_sock);myOverlapped.FreeOverObject(myOverObjectIterator);myOverlapped.RebuildEventArray();cout << "the client socket is close !" << endl;return false;}break;case OP_WRITE: /*发送数据完成*/if(dwTrans > 0){return true;}else{closesocket(myOverObjectIterator->m_sock);myOverlapped.FreeOverObject(myOverObjectIterator);myOverlapped.RebuildEventArray();return false;}break;}}/********************************************************************************* 函数介绍:服务线程函数,平常处于等待状态,完成数据处理。*********************************************************************************/UINT WINAPI ServerThread(PVOID pvParam){while(true){int index;DWORD eventNum = (DWORD)(myOverlapped.eventArray.size());index = ::WSAWaitForMultipleEvents(eventNum, &(myOverlapped.eventArray[0]), false, WSA_INFINITE, false);if(index == WSA_WAIT_FAILED){cout << "wait error is : " << ::GetLastError() << endl;break;}else{index = index - WSA_WAIT_EVENT_0;if(myOverlapped.IsAcceptEvent(index)){myOverlapped.ResetAcceptEvent();continue;}list<OverObject>::iterator nowIterator = (myOverlapped.FindOverObject(myOverlapped.eventArray[index]));if(nowIterator != NULL){bool ret = OperateFunction(nowIterator);if(ret){::WSAResetEvent(myOverlapped.eventArray[index]);myOverlapped.PostRecv(nowIterator);}}}}return 0;}
0 0
- 【整理】重叠IO模型的编程思路及C++源代码
- 关于重叠IO网络编程模型的学习!
- 重叠模型IO的优点
- windows Socket编程之重叠IO模型
- 【Windows网络编程】重叠IO网络模型
- 基于事件的重叠IO模型
- 重叠IO模型
- 重叠IO模型
- 重叠IO模型
- 重叠IO模型示例
- IO重叠模型代码
- WINDOWS重叠IO模型
- winsock重叠IO模型
- 重叠IO模型
- 重叠IO模型
- WINDOWS重叠IO模型
- 重叠IO模型
- WINDOWS重叠IO模型
- android include标签的使用,在RelativeLayout中使用include标签需注意!!!!!
- linux remote machin exec command
- 保护眼睛的电脑设置
- eclipse生成jar包
- mac下制作centos usb 安装盘
- 【整理】重叠IO模型的编程思路及C++源代码
- view写雷达效果
- HDU 1166 敌兵布阵(线段树基础)
- 测试磁盘IO速度
- Visual Studio 2010 “VC++ 目录”属性页
- raw_contacts表中 version普通数据修改+1 头像修改+3
- 四川一对夫妻生育3孩子:遗弃1个 贩卖1个
- 海思各种分区说明,默认修改配置说明
- DataView .RowFilter 使用