python iocp_[网络开发]IOCP完整例子

本文是我在学习IOCP的时候,第一次写一个完整的例子出来,当然了,参考了CSDN上一些朋友的博客,大部分都是按照他们的思路写的,毕竟我是初学者,参考现成的学起来比较快。当然了,真正用到项目中的IOCP肯定不止这么简单的,还有内存池,环形缓冲区,socket连接池等高端内容,后面我会参考一些例子,写出一个完整的给大家看。

/************************************************************************

FileName:iocp.h

Author :eliteYang

http://www.cppfans.org

************************************************************************/

#ifndef __IOCP_H__

#define __IOCP_H__

#include

#include

#define DefaultPort 20000

#define DataBuffSize 8 * 1024

typedef struct

{

OVERLAPPED overlapped;

WSABUF databuff;

CHAR buffer[ DataBuffSize ];

DWORD bytesSend;

DWORD bytesRecv;

}PER_IO_OPERATEION_DATA, *LPPER_IO_OPERATION_DATA;

typedef struct

{

SOCKET socket;

}PER_HANDLE_DATA, *LPPER_HANDLE_DATA;

#endif

前面讲过IOCP里面一个很重要的东西就是IO重叠了,所以结构体里有一个OVERLAPPED结构。

/************************************************************************

FileName:iocp.cpp

Author :eliteYang

http://www.cppfans.org

************************************************************************/

#include "iocp.h"

#include

using namespace std;

#pragma comment( lib, "Ws2_32.lib" )

DWORD WINAPI ServerWorkThread( LPVOID CompletionPortID );

void main()

{

SOCKET acceptSocket;

HANDLE completionPort;

LPPER_HANDLE_DATA pHandleData;

LPPER_IO_OPERATION_DATA pIoData;

DWORD recvBytes;

DWORD flags;

WSADATA wsaData;

DWORD ret;

if ( ret = WSAStartup( 0x0202, &wsaData ) != 0 )

{

std::cout << "WSAStartup failed. Error:" << ret << std::endl;

return;

}

completionPort = CreateIoCompletionPort( INVALID_HANDLE_VALUE, NULL, 0, 0 );

if ( completionPort == NULL )

{

std::cout << "CreateIoCompletionPort failed. Error:" << GetLastError() << std::endl;

return;

}

SYSTEM_INFO mySysInfo;

GetSystemInfo( &mySysInfo );

// 创建 2 * CPU核数 + 1 个线程

DWORD threadID;

for ( DWORD i = 0; i < ( mySysInfo.dwNumberOfProcessors * 2 + 1 ); ++i )

{

HANDLE threadHandle;

threadHandle = CreateThread( NULL, 0, ServerWorkThread, completionPort, 0, &threadID );

if ( threadHandle == NULL )

{

std::cout << "CreateThread failed. Error:" << GetLastError() << std::endl;

return;

}

CloseHandle( threadHandle );

}

// 启动一个监听socket

SOCKET listenSocket = WSASocket( AF_INET, SOCK_STREAM, 0, NULL, 0, WSA_FLAG_OVERLAPPED );

if ( listenSocket == INVALID_SOCKET )

{

std::cout << " WSASocket( listenSocket ) failed. Error:" << GetLastError() << std::endl;

return;

}

SOCKADDR_IN internetAddr;

internetAddr.sin_family = AF_INET;

internetAddr.sin_addr.s_addr = htonl( INADDR_ANY );

internetAddr.sin_port = htons( DefaultPort );

// 绑定监听端口

if ( bind( listenSocket, (PSOCKADDR)&internetAddr, sizeof( internetAddr ) ) == SOCKET_ERROR )

{

std::cout << "Bind failed. Error:" << GetLastError() << std::endl;

return;

}

if ( listen( listenSocket, 5 ) == SOCKET_ERROR )

{

std::cout << "listen failed. Error:" << GetLastError() << std::endl;

return;

}

// 开始死循环,处理数据

while ( 1 )

{

acceptSocket = WSAAccept( listenSocket, NULL, NULL, NULL, 0 );

if ( acceptSocket == SOCKET_ERROR )

{

std::cout << "WSAAccept failed. Error:" << GetLastError() << std::endl;

return;

}

pHandleData = (LPPER_HANDLE_DATA)GlobalAlloc( GPTR, sizeof( PER_HANDLE_DATA ) );

if ( pHandleData = NULL )

{

std::cout << "GlobalAlloc( HandleData ) failed. Error:" << GetLastError() << std::endl;

return;

}

pHandleData->socket = acceptSocket;

if ( CreateIoCompletionPort( (HANDLE)acceptSocket, completionPort, (ULONG_PTR)pHandleData, 0 ) == NULL )

{

std::cout << "CreateIoCompletionPort failed. Error:" << GetLastError() << std::endl;

return;

}

pIoData = ( LPPER_IO_OPERATION_DATA )GlobalAlloc( GPTR, sizeof( PER_IO_OPERATEION_DATA ) );

if ( pIoData == NULL )

{

std::cout << "GlobalAlloc( IoData ) failed. Error:" << GetLastError() << std::endl;

return;

}

ZeroMemory( &( pIoData->overlapped ), sizeof( pIoData->overlapped ) );

pIoData->bytesSend = 0;

pIoData->bytesRecv = 0;

pIoData->databuff.len = DataBuffSize;

pIoData->databuff.buf = pIoData->buffer;

flags = 0;

if ( WSARecv( acceptSocket, &(pIoData->databuff), 1, &recvBytes, &flags, &(pIoData->overlapped), NULL ) == SOCKET_ERROR )

{

if ( WSAGetLastError() != ERROR_IO_PENDING )

{

std::cout << "WSARecv() failed. Error:" << GetLastError() << std::endl;

return;

}

else

{

std::cout << "WSARecv() io pending" << std::endl;

return;

}

}

}

}

DWORD WINAPI ServerWorkThread( LPVOID CompletionPortID )

{

HANDLE complationPort = (HANDLE)CompletionPortID;

DWORD bytesTransferred;

LPPER_HANDLE_DATA pHandleData = NULL;

LPPER_IO_OPERATION_DATA pIoData = NULL;

DWORD sendBytes = 0;

DWORD recvBytes = 0;

DWORD flags;

while ( 1 )

{

if ( GetQueuedCompletionStatus( complationPort, &bytesTransferred, (PULONG_PTR)&pHandleData, (LPOVERLAPPED *)&pIoData, INFINITE ) == 0 )

{

std::cout << "GetQueuedCompletionStatus failed. Error:" << GetLastError() << std::endl;

return 0;

}

// 检查数据是否已经传输完了

if ( bytesTransferred == 0 )

{

std::cout << " Start closing socket..." << std::endl;

if ( CloseHandle( (HANDLE)pHandleData->socket ) == SOCKET_ERROR )

{

std::cout << "Close socket failed. Error:" << GetLastError() << std::endl;

return 0;

}

GlobalFree( pHandleData );

GlobalFree( pIoData );

continue;

}

// 检查管道里是否有数据

if ( pIoData->bytesRecv == 0 )

{

pIoData->bytesRecv = bytesTransferred;

pIoData->bytesSend = 0;

}

else

{

pIoData->bytesSend += bytesTransferred;

}

// 数据没有发完,继续发送

if ( pIoData->bytesRecv > pIoData->bytesSend )

{

ZeroMemory( &(pIoData->overlapped), sizeof( OVERLAPPED ) );

pIoData->databuff.buf = pIoData->buffer + pIoData->bytesSend;

pIoData->databuff.len = pIoData->bytesRecv - pIoData->bytesSend;

// 发送数据出去

if ( WSASend( pHandleData->socket, &(pIoData->databuff), 1, &sendBytes, 0, &(pIoData->overlapped), NULL ) == SOCKET_ERROR )

{

if ( WSAGetLastError() != ERROR_IO_PENDING )

{

std::cout << "WSASend() failed. Error:" << GetLastError() << std::endl;

return 0;

}

else

{

std::cout << "WSASend() failed. io pending. Error:" << GetLastError() << std::endl;

return 0;

}

}

std::cout << "Send " << pIoData->buffer << std::endl;

}

else

{

pIoData->bytesRecv = 0;

flags = 0;

ZeroMemory( &(pIoData->overlapped), sizeof( OVERLAPPED ) );

pIoData->databuff.len = DataBuffSize;

pIoData->databuff.buf = pIoData->buffer;

if ( WSARecv( pHandleData->socket, &(pIoData->databuff), 1, &recvBytes, &flags, &(pIoData->overlapped), NULL ) == SOCKET_ERROR )

{

if ( WSAGetLastError() != ERROR_IO_PENDING )

{

std::cout << "WSARecv() failed. Error:" << GetLastError() << std::endl;

return 0;

}

else

{

std::cout << "WSARecv() io pending" << std::endl;

return 0;

}

}

}

}

}

整个过程还是类似于最基础的socket连接方式,主要部分就是使用IOCP的两个函数,创建IOCP和检测当前的状态。

大家先凑活看吧,后面本博客会有更精彩的IOCP内容呈现给大家,我也是逐步在学习,大家稍安勿躁。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值