UDP的IOCP方式

class CIOCPServer
{
 CString m_sConnectString;


public:
 CDatabase m_Database;
 /*读起用户信息到内存*/
 CIOCPServer();
 virtual ~CIOCPServer();

 //2005.6.2
 BOOL StartServer();
 BOOL StopServer();


 BOOL InitSocket(SOCKET_STYPE stype,int port, int num = -1);

 //绑定在端口上工作线程
 static DWORD WINAPI CompletionWorkerThread( void * lpParam);

private:
 BOOL ProcessLoadMsg(LPCLIENTCONTEXT lpContext);

private:
 //根据消息overlapped的类型,处理消息
 BOOL ProcessIOMessage(SOCKET_STYPE stype,IOType opCode, LPCLIENTCONTEXT lpContext , DWORD dwIoSize);

 //在端口上产生线程,并创建完成端口
 void CreateWorkerThread();
 //关闭完成端口
 void CloseCompletionPort();
 //分配连接overlappedplus
 LPOVERLAPPEDPLUS AllocateOverlappedPlus(IOType ioType);
 //分配连接进入的客户的相关信息
 LPCLIENTCONTEXT AllocateContext();
 //释放overlappedplus
 void FreeOverlappedPlus(LPOVERLAPPEDPLUS lpOlp);
private:

 HANDLE m_hIocp; //完成端口句柄
 DWORD m_dwThreads; //线程数
};

CPP方式:
#include "IOCPServer.h"

#include "common.h"

CIOCPServer::CIOCPServer()
{

 //socket初始化
 WSADATA wsd;
 WORD wVersionRequested = MAKEWORD(2, 2);
 int nResult = WSAStartup(wVersionRequested, &wsd);
 if (nResult == SOCKET_ERROR)
 {
 WSACleanup();
 }

 if (LOBYTE(wsd.wVersion) != 2 || HIBYTE(wsd.wVersion) != 2)
 {
 WSACleanup();
 }


}

CIOCPServer::~CIOCPServer()
{
 WSACleanup();
}


//分配连接overlappedplus
LPOVERLAPPEDPLUS CIOCPServer::AllocateOverlappedPlus(IOType ioType)
{
 OVERLAPPEDPLUS* pOlp = NULL;

 pOlp = new OVERLAPPEDPLUS;
 ZeroMemory(pOlp, sizeof(OVERLAPPEDPLUS));
 pOlp->opCode = ioType;

 return pOlp;

}

//分配连接进入的客户的相关信息
LPCLIENTCONTEXT CIOCPServer::AllocateContext()
{
 LPCLIENTCONTEXT lpContext = NULL;

 lpContext = new CLIENTCONTEXT;
 ZeroMemory(lpContext, sizeof(CLIENTCONTEXT));
 lpContext->m_wsaBuffer.buf = lpContext->m_Buffer;
 lpContext->m_wsaBuffer.len = BUFSIZE;

 return lpContext;

}

//释放overlappedplus
void CIOCPServer::FreeOverlappedPlus(LPOVERLAPPEDPLUS lpOlp)
{
 delete lpOlp;
}


//根据消息overlapped的类型,处理消息,返回值TRUE:继续读,FALSE,不读
//一般写事件就不让他都返回FALSE,没有必要再读了!
BOOL CIOCPServer::ProcessIOMessage(SOCKET_STYPE stype,IOType opCode, LPCLIENTCONTEXT lpContext , DWORD dwIoSize)
{
 BOOL bRet = FALSE;

 //根据stype确定操作
 switch (stype)
 {
 case LOAD_SOCKET:
 ProcessLoadMsg(lpContext);
 break;
 }

 return TRUE;
}

//关闭完成端口
void CIOCPServer::CloseCompletionPort( )
{
 PostQueuedCompletionStatus(m_hIocp, 0, (DWORD) NULL, NULL);

 // Close the CompletionPort and stop any more requests
 CloseHandle(m_hIocp);

}

 

void CIOCPServer::CreateWorkerThread()
{
 SYSTEM_INFO sysinfo;
 DWORD dwThreadId;

 //在completion port上等待的线程数为:CPU*2+2
 GetSystemInfo(&sysinfo);
 m_dwThreads = sysinfo.dwNumberOfProcessors*2+2;

 for(UINT i=0;i {
 HANDLE hThread;
 hThread = CreateThread(NULL,
 0,
 CompletionWorkerThread,
 (LPVOID)this,
 0,
 &dwThreadId);
 CloseHandle(hThread);
 }
 //产生完成端口
 m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
 if(m_hIocp == NULL)
 {
 return;
 }

}

//绑定在端口上工作线程
DWORD WINAPI CIOCPServer::CompletionWorkerThread( void * lpParam)
{
 CIOCPServer *pIocpServer = (CIOCPServer *)lpParam;

 DWORD dwNumRead;
 LPCLIENTCONTEXT lpContext;
 LPWSAOVERLAPPED lpOverlapped;
 LPOVERLAPPEDPLUS lpOlp;

 while (TRUE)
 {
 BOOL bError = FALSE;
 BOOL bEnterRead = TRUE;

 BOOL bResult = GetQueuedCompletionStatus(pIocpServer->m_hIocp,
 &dwNumRead,
 (LPDWORD)&lpContext,
 &lpOverlapped,
 INFINITE);

 //获得LPOVERLAPPEDPLUS指针
 lpOlp = CONTAINING_RECORD(lpOverlapped, OVERLAPPEDPLUS, ol);

 if (dwNumRead == 0){
 return 0;
 }
 //非timeout引起的错误, 相关信息没有从GetQueuedCompletionStatus中返回
 if (!bResult && lpOlp == NULL && WAIT_TIMEOUT != WSAGetLastError())
 {
 // 发生错误
 bError = TRUE;
 }
 //错误,但是相关信息从GetQueuedCompletionStatus中返回
 //可能原因之一是:客户强制退出了!
 else if(!bResult && lpOlp != NULL)
 {
 //循环继续,不应该读了!
 continue;
 }

 //无错误,处理事件
 if (!bError)
 {
 if(bResult && NULL != lpOlp && NULL != lpContext)
 {
 bEnterRead = pIocpServer->ProcessIOMessage(lpContext->m_stype,lpOlp->opCode, lpContext, dwNumRead);
 }
 }

 //重新初试化
 if(! bError && bEnterRead)
 {
 LPOVERLAPPEDPLUS lpOlp = pIocpServer->AllocateOverlappedPlus(OP_IORead);
 ULONG ulFlags = MSG_PARTIAL;

 ZeroMemory(lpContext->m_wsaBuffer.buf, lpContext->m_wsaBuffer.len);
 int len = sizeof(sockaddr_in);
 UINT nRetVal = WSARecvFrom(lpContext->m_Socket,
 &lpContext->m_wsaBuffer,
 1,
 0,
 &ulFlags,
 (sockaddr*)&lpContext->m_fromaddr,&len,
 &lpOlp->ol,
 NULL);

 if ( nRetVal == SOCKET_ERROR && WSAGetLastError() != WSA_IO_PENDING)
 return FALSE;

 }

 pIocpServer->FreeOverlappedPlus(lpOlp);

 }
 return 0;
}


BOOL CIOCPServer::InitSocket(SOCKET_STYPE stype,int port,int num)
{
 //bind SOCKET to completion port and init first work
 LPCLIENTCONTEXT LoadListenData = AllocateContext();
 if (LoadListenData == NULL)
 return FALSE;

 LoadListenData->m_Socket = WSASocket(AF_INET, SOCK_DGRAM, IPPROTO_IP, NULL, 0, WSA_FLAG_OVERLAPPED);
 if(LoadListenData->m_Socket == SOCKET_ERROR)
 return FALSE;

 //需要绑定的本地地址
 sockaddr_in local;
 memset(&local, 0, sizeof(local));
 local.sin_addr.s_addr = htonl(INADDR_ANY);
 local.sin_family = AF_INET;
 local.sin_port = htons(port);

 //绑定,将监听端口绑定到本地地址
 if(bind(LoadListenData->m_Socket, (sockaddr*)&local,sizeof(local))
 == SOCKET_ERROR)
 return FALSE;



 LoadListenData->m_stype = stype;
 LoadListenData->m_nNum = num;
 HANDLE hrc = CreateIoCompletionPort((HANDLE)LoadListenData->m_Socket,m_hIocp,(DWORD)LoadListenData,0);
 if (NULL == hrc)
 return FALSE;


 int len = sizeof(sockaddr_in);

 LPOVERLAPPEDPLUS lpOlp = AllocateOverlappedPlus(OP_IORead);
 ULONG ulFlags = MSG_PARTIAL;

 int iret = WSARecvFrom(LoadListenData->m_Socket,
 &(LoadListenData->m_wsaBuffer),
 1,NULL,
 &ulFlags,
 (sockaddr*)&LoadListenData->m_fromaddr,&len,
 &lpOlp->ol,
 NULL
 );
 if (iret == SOCKET_ERROR && WSAGetLastError() != ERROR_IO_PENDING)
 return FALSE;

 return TRUE;
}

BOOL CIOCPServer::StartServer()
{
 m_Database.OpenEx("DSN=SASSYSTEM;UID=;PWD=");
 CreateWorkerThread();
 if(!InitSocket(LOAD_SOCKET,14688))
 AfxMessageBox("fair");
 return TRUE;
}

BOOL CIOCPServer::StopServer()
{

 CloseCompletionPort();
 return TRUE;
}

BOOL CIOCPServer::ProcessLoadMsg(LPCLIENTCONTEXT lpContext)
{

//lpContext->m_Buffer就是你接收到的数据信息了

 //调试信息
 /* char buf[200];
 memset(buf,0,sizeof(buf));
 memcpy(buf,lpContext->m_Buffer,200);
 FILE * file;
 file=fopen("BUF内容.txt","w");
 for(int i=0;i<100;i++)
 {
 fprintf(file,"%s",buf+i);
 }
 fprintf(file,"over");
 fclose(file);
 */
 return TRUE;
}

 

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: IOCP(输入输出完成端口)是一种高效的异步通信模型,UDP是一种面向无连接的传输协议,C是一种编程语言。所以"IOCP UDP C demo"可以理解为使用IOCP和C语言实现的UDP通信示例。 在这个示例中,我们可以使用C语言编写一个简单的程序,通过UDP协议进行数据的传输。首先,我们需要创建一个UDP套接字,通过该套接字与远程主机进行通信。接收方需要创建一个IOCP对象,并将套接字绑定在该IOCP对象上,以便异步地接收数据。 发送方可以使用sendto函数将数据发送给接收方。数据可以是任意类型的,例如文字、图片或者音频等。发送方只需要将数据写入套接字,并指定接收方的IP地址和端口号。 接收方在接收到数据时,会触发IOCP的回调函数,我们可以在回调函数中对数据进行处理。可以根据需要对数据进行解析或者存储等操作。 在整个过程中,IOCP实现了异步的数据传输,可以同时处理多个连接,提高了系统的性能。 总结来说,IOC UDP C demo是一个使用IOCP和C语言实现的UDP通信示例程序,可以通过该示例了解IOCP的异步通信模型和C语言的编程技巧,以及UDP协议在网络通信中的应用。 ### 回答2: IOCP(Input/Output Completion Port)是一种高效的 I/O 处理机制,UDP(User Datagram Protocol)是一种无连接的传输协议,C 是一种编程语言,在下面的回答中,我将简要介绍 IOCp UDP C demo 的相关内容。 IOCp UDP C demo 是一个基于 IOCP 模型开发的 UDP 网络通信的示例程序,使用 C 语言编写。该示例程序主要用于展示如何使用 IOCP 来实现高性能的 UDP 网络通信。 在该示例程序中,首先会创建一个 IOCP 对象,并将其与一个 UDP 套接字绑定。然后,程序会创建多个工作者线程,每个线程都会调用 GetQueuedCompletionStatus 函数来等待 I/O 完成的通知。 当有 I/O 操作完成时,工作者线程会收到通知,并通过相关的数据结构获取完成的信息,比如接收到的数据、发送是否成功等。然后,线程根据具体的业务需求进行相应的处理,比如解析接收到的数据、发送响应等。 IOCP 可以实现高并发的网络通信,因为它使用了事件驱动的模型,可以同时处理多个 I/O 请求。而 UDP 是无连接的,没有连接的建立和断开的开销,适合实时性要求较高的应用场景,比如游戏中的实时通信。 通过这个示例程序,可以更好地了解 IOCP 模型的基本原理和使用方法,以及如何使用 UDP 进行高性能的网络通信。同时,可以根据自身需求进行改进和扩展,实现更复杂的网络应用。 总之,IOCp UDP C demo 是一个基于 IOCP 模型开发的 UDP 网络通信的示例程序,通过该示例程序可以学习和理解 IOCP 模型和 UDP 网络通信的相关知识。 ### 回答3: IOC(Input/Output Completion Ports)是一种高效的异步输入输出模型,UDP(User Datagram Protocol)是一种无连接的传输协议,而C Demo则指的是使用C语言编写的演示程序。 IOCUDP可以结合使用,通过IOC监听网络IO事件,实现高吞吐量的UDP数据传输。在C Demo中,我们可以使用Windows平台提供的IOCP机制,在C语言中编写代码来演示如何使用IOCUDP。 在C Demo中,首先需要创建一个套接字,用于监听和发送UDP数据包。然后,创建一个IOCP对象,用于管理套接字的异步IO操作。接下来,将套接字与IOCP对象关联起来,以便在IO事件发生时能够收到通知。 在程序运行时,我们可以使用多个线程来同时处理多个UDP连接。每个线程都会从IOCP对象中获取完成的IO事件,并根据不同的事件类型进行相应的处理。例如,当有数据包到达时,可以直接从套接字中读取数据并进行处理;当需要发送数据包时,可以将数据包写入套接字并发送。 通过使用IOCUDP,我们可以实现高效的网络数据传输,同时充分利用系统资源,提高程序的性能和响应速度。C Demo可以帮助我们理解和学习如何使用IOCUDP编写高性能的网络应用程序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值