iocp例子

<span style="font-size:18px;"></pre><pre name="code" class="cpp"><pre name="code" class="cpp">main函数和工作线程文件
</span>
<span style="font-size:18px;">#include "stdafx.h"
#include <WinSock2.h>
#include "CDSocket.h"
#pragma comment(lib, "ws2_32.lib")


struct PER_HANDLE_DATA
{
	SOCKET s;
	sockaddr_in addr;
	PER_HANDLE_DATA (SOCKET s0, sockaddr_in addr0) : s(s0), addr(addr0){}
};

struct PER_IO_DATA
{
	WSAOVERLAPPED ol;
	char buf[BUFFER_SIZE];
	int nOperation;
	PER_IO_DATA (int op)
	{
		ZeroMemory(this, sizeof(PER_IO_DATA));
		nOperation = op;
	}
};

DWORD WINAPI ServerThread(LPVOID lpParam);


SockInit si;


int _tmain(int argc, _TCHAR* argv[])
{
	//创建完成端口
	HANDLE hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, 0, 0, 0);
	//创建工作线程
	HANDLE hThread = CreateThread(NULL, 0, ServerThread, (LPVOID)hIocp, 0, 0);
	//创建socket
	CDSocket sListen;
	sListen.Create();
	//绑定
	sListen.Bind(4567);
	//监听
	sListen.Listen();

	while (true)
	{
		//接受连接
		sockaddr_in remoteAddr;
		
		CDSocket sRemote = sListen.Accept((sockaddr*)&remoteAddr);
		printf("接受ip=%s port=%d的连接\n", inet_ntoa(remoteAddr.sin_addr), ntohs(remoteAddr.sin_port));
		//连接socket关联完成端口
		PER_HANDLE_DATA* pPerHandle = new PER_HANDLE_DATA(sRemote, remoteAddr);
		
		CreateIoCompletionPort((HANDLE)pPerHandle->s, hIocp, (ULONG_PTR)pPerHandle, 0);
		
		//投递异步接收请求
	/*	PER_IO_DATA* pPerIO = (PER_IO_DATA *)::GlobalAlloc(GPTR, sizeof(PER_IO_DATA));
		pPerIO->nOperation = OP_READ;
		OVERLAPPED结构必须为0 否则一定失败 tmd老子调了一下午
		*/
		PER_IO_DATA* pPerIO = new PER_IO_DATA(OP_READ);
		sRemote.Recv(pPerIO->buf, BUFFER_SIZE, NULL, (LPWSAOVERLAPPED)pPerIO);
	}
	
	return 0;
}


DWORD WINAPI ServerThread(LPVOID lpParam)
{
	HANDLE hIocp = (HANDLE)lpParam;
	DWORD dwTrans;
	PER_HANDLE_DATA* pPerHandle = NULL;
	PER_IO_DATA* pPerIO = NULL;
	while (true)
	{
		BOOL bOK = GetQueuedCompletionStatus(hIocp, &dwTrans, (PULONG_PTR)&pPerHandle, (LPOVERLAPPED*)&pPerIO, WSA_INFINITE);
		if (!bOK)
		{
			closesocket(pPerHandle->s);
			delete pPerHandle;
			delete pPerIO;
			continue;
		}
		if (dwTrans == 0 && (pPerIO->nOperation == OP_READ || pPerIO->nOperation == OP_WRITE))
		{
			closesocket(pPerHandle->s);
			delete pPerHandle;
			delete pPerIO;
			continue;
		}
		switch (pPerIO->nOperation)
		{
			case OP_READ:
			{
							pPerIO->buf[dwTrans] = '\0';
							printf(pPerIO->buf);
							/*WSABUF buf;
							buf.buf = pPerIO->buf;
							buf.len = BUFFER_SIZE;
							pPerIO->nOperation = OP_READ;
							DWORD nFlags = 0;
							WSARecv(pPerHandle->s, &buf, 1, &dwTrans, &nFlags, lpOverLapped, NULL);*/
							CDSocket sClient(pPerHandle->s);
							//sClient.Recv(pPerIO->buf, BUFFER_SIZE, NULL, (LPWSAOVERLAPPED)pPerIO);
							sClient.Send(pPerIO->buf, strlen(pPerIO->buf));
			}
			case OP_WRITE:
			{

			}
			case OP_ACCEPT:
			{

			}

			default:
				break;
		}
	}
	return 0;
}
</span>

需要的两个socket封装类
 
<span style="font-size:18px;">//SockInit是初始化socket环境的类,定义一个此类的全局变量即可</span>
<span style="font-size:18px;">//socket的简单封装CDSocket.h
#include <WinSock2.h>


#define BUFFER_SIZE 1024
#define OP_READ		1
#define OP_WRITE	2
#define OP_ACCEPT	3


struct SockInit
{
	SockInit()
	{
		WSADATA wsaData;
		WSAStartup(MAKEWORD(2, 2), &wsaData);
	}
	~SockInit()
	{
		WSACleanup();
	}
};


class CDSocket
{
public:
	CDSocket(SOCKET hSocket = NULL) :m_hSocket(hSocket)
	{}
	~CDSocket()
	{
		if (m_hSocket != NULL)
		{
			closesocket(m_hSocket);
		}
	}

	CDSocket& operator=(const CDSocket& rhs)
	{
		if (m_hSocket != NULL)
		{
			closesocket(m_hSocket);
		}
		m_hSocket = rhs.m_hSocket;
		return *this;
	}

	CDSocket& operator=(const SOCKET& hSocket)
	{
		if (m_hSocket != NULL)
		{
			closesocket(m_hSocket);
		}
		m_hSocket = hSocket;
		return *this;
	}

	bool Create()
	{
		m_hSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (INVALID_SOCKET == m_hSocket)
		{
			m_hSocket = NULL;
			return false;
		}
		return true;
	}
	int Bind(short nPort)
	{
		sockaddr_in localAddr;
		localAddr.sin_family = AF_INET;
		localAddr.sin_port = ntohs(nPort);
		localAddr.sin_addr.S_un.S_addr = INADDR_ANY;
		return bind(m_hSocket, (sockaddr*)&localAddr, sizeof(localAddr));
	}
	int Listen(int backend = 10)
	{
		return listen(m_hSocket, backend);
	}

	CDSocket Accept(sockaddr* remoteAddr)
	{
		int nRemoteAddrLen = sizeof(sockaddr);
		return CDSocket(accept(m_hSocket, remoteAddr, &nRemoteAddrLen));
	}

	int Connect(const char* szIp, short nPort)
	{
		sockaddr_in remoteAddr;
		remoteAddr.sin_family = AF_INET;
		remoteAddr.sin_port = ntohs(nPort);
		remoteAddr.sin_addr.S_un.S_addr = inet_addr(szIp);
		return connect(m_hSocket, (sockaddr*)&remoteAddr, sizeof(remoteAddr));
	}

	int Send(char* szBuf, int len)
	{
		return send(m_hSocket, szBuf, len, 0);
	}

	int Recv(char* szBuf, int nBufSize, LPDWORD lpNumberOfBytesRecvd, LPWSAOVERLAPPED lpOverLapped)
	{
		WSABUF buf;
		buf.buf = szBuf;
		buf.len = nBufSize;
		DWORD dwFlags = 0;
		return WSARecv(m_hSocket, &buf, 1, lpNumberOfBytesRecvd, &dwFlags, lpOverLapped, NULL);
	}

	operator SOCKET()
	{
		return m_hSocket;
	}

	void Attach(SOCKET hSocket)
	{
		if (m_hSocket != NULL)
		{
			closesocket(m_hSocket);
		}
		m_hSocket = hSocket;
	}


private:
	SOCKET m_hSocket;
};</span>




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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值