首页 > 编程知识 正文

有哪些失败转为成功的例子,发现与突转的例子

时间:2023-05-04 12:59:01 阅读:62702 作者:3586

【转发】IOCP协助AcceptEx的例子

原文地址: http://laokaddk.blog.51cto.com/368606/610145 /

本程序由VS2003编译器编译运行。 6.0可能需要稍微修改。

# include iostream # include Winsock2. h # include ws2 tcpip.h # include mswsock.h//微软扩展类库using namespace std; # define send0# define recv1# define accept2# definedata _ length 1000//单句柄数据定义typedef struct _ per _ handle _ data //客户端地址}PER_HANDLE_DATA,*LPPER_HANDLE_DATA; //但IO操作数据typedef struct { overlapped overlapped; wsabuf缓冲区; 用于WSASend/WSARecv第二参数char数据缓冲器[ data _ length ]的数据缓冲区; //实际数据缓冲区int dataLength; //实际数据缓冲区长度int操作器类型; //操作类型为SEND/RECV两种套接字客户端; //分别表示发送的字节数和接收的字节数的(}PER_IO_DATA、*LPPER_IO_DATA; void main () {HANDLE CompletionPort; wsadata数据; SYSTEM_INFO info; SOCKADDR_IN addr; 套接字列表; 无符号输入I; wsa启动(make word ) 2,2 ),data ); //io完成端口创建完成端口=createiocompletionport (invalid _ handle _ value,NULL,0,0 ); //决定处理器数量的获取系统信息(info ); //制作线路城市for (I=0; iinfo.dwNumberOfProcessors * 2; I )//根据处理器数量正确创建处理线程的handlethread=createthread(NULL,0,ServerThread,CompletionPort,0,null ); 闭合手柄(thread; (//创建监听套接字) listen=WSAsocket(af_inet,SOCK_STREAM,0,NULL,0,WSA_FLAG_OVERLAPPED ); //将监听套接字放在完成端口上LPPER_HANDLE_DATA perDandleData; perdandledata=(lpper _ handle _ data ) globalalloc ) gptr,sizeof(per_handle_data ); perDandleData-socket=Listen; createioCompletionPort((handle ) Listen,completionport,) (ULONG_PTR ) perDandleData,0 ); addr.sin_family=AF_INET; addr.sin _ addr.s _ addr=htonl (in addr _ any ); ADDR.sin_port=htons(5500; bind(listen,) p sockaddr (addr,sizeof ) addr ); 监听器(listen,5 ); LPFN_ACCEPTEX lpfnAcceptEx=NULL; //AcceptEx函数指针//acceptfunctionguidguidacceptex=w said _ acceptex; //getacceptexfunctionpointerdworddwbytes=0; if(WSAioctl(listen,SiO _ get _ extension _ function _ pointer,guidAcceptEx,sizeof ) guidAcceptEx ),lpfnAcceptEx

=0)         cout<<"WSAIoctl success..."<<endl;     else{         cout<<"WSAIoctl failed..."<<endl;         switch(WSAGetLastError())         {         case WSAENETDOWN:             cout<<""<<endl;             break;         case WSAEFAULT:             cout<<"WSAEFAULT"<<endl;             break;         case WSAEINVAL:             cout<<"WSAEINVAL"<<endl;             break;         case WSAEINPROGRESS:             cout<<"WSAEINPROGRESS"<<endl;             break;         case WSAENOTSOCK:             cout<<"WSAENOTSOCK"<<endl;             break;         case WSAEOPNOTSUPP:             cout<<"WSAEOPNOTSUPP"<<endl;             break;         case WSA_IO_PENDING:             cout<<"WSA_IO_PENDING"<<endl;             break;         case WSAEWOULDBLOCK:             cout<<"WSAEWOULDBLOCK"<<endl;             break;         case WSAENOPROTOOPT:             cout<<"WSAENOPROTOOPT"<<endl;             break;         }         return;     }     //while(true)     //{         //准备调用 AcceptEx 函数,该函数使用重叠结构并于完成端口连接         LPPER_IO_DATA perIoData = (LPPER_IO_DATA)GlobalAlloc(GPTR,sizeof(PER_IO_DATA));         memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));             perIoData->operatorType = ACCEPT;         //在使用AcceptEx前需要事先重建一个套接字用于其第二个参数。这样目的是节省时间         //通常可以创建一个套接字库         perIoData->client = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_TCP,0,0,WSA_FLAG_OVERLAPPED);         perIoData->dataLength = DATA_LENGTH;         DWORD flags = 0;                 //调用AcceptEx函数,地址长度需要在原有的上面加上16个字节         //注意这里使用了重叠模型,该函数的完成将在与完成端口关联的工作线程中处理         cout<<"Process AcceptEx function wait for client connect..."<<endl;         int rc = lpfnAcceptEx(Listen,perIoData->client,perIoData->dataBuffer,             perIoData->dataLength-((sizeof(SOCKADDR_IN)+16)*2),             sizeof(SOCKADDR_IN)+16,sizeof(SOCKADDR_IN)+16,&dwBytes,             &(perIoData->overlapped));         if(rc == FALSE)         {             if(WSAGetLastError()!=ERROR_IO_PENDING)                 cout<<"lpfnAcceptEx failed.."<<endl;         }         cin>>i;     closesocket(Listen);     WSACleanup();}DWORD WINAPI ServerThread(LPVOID lpParam){     HANDLE CompletionPort = (HANDLE)lpParam;     DWORD bytes;     LPPER_HANDLE_DATA perHandleData = NULL;     //单句柄数据     LPPER_IO_DATA perIoData;             //单IO数据     DWORD Flags;     int ret;     DWORD RecvBytes;     //进入循环的等待重叠操作的完成     while(true)     {         bytes = -1;         ret=GetQueuedCompletionStatus(             CompletionPort,                 //原先的完成端口句柄             &bytes,                         //重叠操作完成的字节数             (LPDWORD)&perHandleData,     //原先和完成端口句柄关联起来的单句柄数据             (LPOVERLAPPED*)&perIoData,     //用于接收已完成的IO操作的重叠结构             INFINITE);                     //在完成端口上等待的时间 INFINITE 为无限等待                 //先检查在套接字上是否发生错误         //当发生错误时关闭套接字同时释放掉所有的内存.         int i = 0;         if(bytes == 0 && (perIoData->operatorType == RECV ||             perIoData->operatorType == SEND))         {             closesocket(perHandleData->socket);             GlobalFree(perHandleData);             GlobalFree(perIoData);             cout<<"closesocket and globalfree perhandledata periodata!"<<endl;             continue;         }         //这是AcceptEx函数处理完成,在下面处理         if(perIoData->operatorType == ACCEPT)     //处理连接操作         {             //使用GetAcceptExSockaddrs函数 获得具体的各个地址参数.             if(setsockopt( perIoData->client, SOL_SOCKET, SO_UPDATE_ACCEPT_CONTEXT,                   ( char* )&(perHandleData->socket ), sizeof( perHandleData->socket ) )==SOCKET_ERROR)                 cout<<"setsockopt..."<<endl;             perHandleData->socket = perIoData->client;             //memcpy(&(perHandleData->clientAddr),raddr,sizeof(raddr));             //将新的客户套接字与完成端口连接             CreateIoCompletionPort((HANDLE)perHandleData->socket,                 CompletionPort,(ULONG_PTR)perHandleData,0);             memset(&(perIoData->overlapped),0,sizeof(OVERLAPPED));             perIoData->operatorType = RECV;         //将状态设置成接收             //设置WSABUF结构             perIoData->buffer.buf = perIoData->dataBuffer;             perIoData->buffer.len = perIoData->dataLength = DATA_LENGTH;             cout<<"wait for data arrive(Accept)..."<<endl;             Flags = 0;             if(WSARecv(perHandleData->socket,&(perIoData->buffer),1,                 &RecvBytes,&Flags,&(perIoData->overlapped),NULL)==SOCKET_ERROR)                 if(WSAGetLastError()==WSA_IO_PENDING)                     cout<<"WSARecv Pending..."<<endl;             continue;                     }         if(perIoData->operatorType == RECV)             cout<<perIoData->buffer.buf<<endl;     //将接收到的数据显示出来         Flags = 0;         perIoData->operatorType = RECV;             //设置成接受数据类型         ZeroMemory(&(perIoData->overlapped),sizeof(OVERLAPPED));         //重新投递一个新的接收请求         cout<<" wait for data arrive..."<<endl;         WSARecv(perHandleData->socket,&(perIoData->buffer),1,             &RecvBytes,&Flags,&(perIoData->overlapped),NULL);     }     return 0;} 

 

版权声明:该文观点仅代表作者本人。处理文章:请发送邮件至 三1五14八八95#扣扣.com 举报,一经查实,本站将立刻删除。