⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sunnyasyncsocket.cpp

📁 无线数据服务中心源代码:移动或联通的无限数据终端将采集到的数据通过Internet传送到数据中心
💻 CPP
字号:
f// SunnyAsyncSocket.cpp: implementation of the CSunnyAsyncSocket class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "SunnyAsyncSocket.h"

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSunnyAsyncSocket::CSunnyAsyncSocket(DWORD dwTimeout /*= INFINITE*/) :
	m_hSocket(INVALID_SOCKET),
	m_hEvent(WSA_INVALID_EVENT),
	m_hStopEvent(WSA_INVALID_EVENT),
	m_lEvents(0),
	m_fAutoDelete(FALSE),
	m_dwTimeout(dwTimeout)
{
	m_hStopEvent = WSACreateEvent();
	m_hEvent = WSACreateEvent();

	m_ovRead.Offset = 0;
	m_ovRead.OffsetHigh = 0;
	m_ovRead.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
		
	m_ovWrite.Offset = 0;
	m_ovWrite.OffsetHigh = 0;
	m_ovWrite.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
}

CSunnyAsyncSocket::~CSunnyAsyncSocket()
{
	WSASetEvent(m_hStopEvent);

	m_thread.WaitForEnd();

	if (m_hSocket != INVALID_SOCKET)
	{
		Shutdown();
		::closesocket(m_hSocket);
		m_hSocket = INVALID_SOCKET;
	}

	if (m_hEvent != WSA_INVALID_EVENT)
	{
		WSACloseEvent(m_hEvent);
		m_hEvent = WSA_INVALID_EVENT;
	}
		
	if (m_hStopEvent != WSA_INVALID_EVENT)
	{
		WSACloseEvent(m_hStopEvent);
		m_hStopEvent = WSA_INVALID_EVENT;
	}
	
	if (m_ovRead.hEvent != NULL)
		CloseHandle(m_ovRead.hEvent);

	if (m_ovWrite.hEvent != NULL)
		CloseHandle(m_ovWrite.hEvent);
}

BOOL CSunnyAsyncSocket::Bind(const CIpAddress& ipAddr)
{
	::bind(m_hSocket, &ipAddr, sizeof(ipAddr));
	return TRUE;
}

void CSunnyAsyncSocket::Close()
{
	WSAResetEvent(m_hEvent);
	WSASetEvent(m_hStopEvent);
}

BOOL CSunnyAsyncSocket::Init()
{ 
	if (m_hSocket == INVALID_SOCKET)
		return FALSE;

	WSAResetEvent(m_hStopEvent);

	return m_thread.Create(StaticThreadFunc, this);
}

BOOL CSunnyAsyncSocket::Connect(const CIpAddress& ipAddr)
{
	::connect(m_hSocket, &ipAddr, sizeof(ipAddr));
	return TRUE;
}

BOOL CSunnyAsyncSocket::Create(
		int nSocketType /*= SOCK_STREAM*/,
		long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/,
		const CIpAddress& ipAddr /*= CIpAddress(0,0,0,0:0)*/)
{
	m_hSocket = socket(AF_INET, nSocketType, 0);

	if (m_hSocket != INVALID_SOCKET)
	{
		if (Select(lEvent))
		{
			if (Bind(ipAddr))
			{
				if(Init())
					return TRUE;
			}
		}
	}

	Close();
	return FALSE;
}

BOOL CSunnyAsyncSocket::Select(long lEvent /*= FD_READ | FD_WRITE | FD_OOB | FD_ACCEPT | FD_CONNECT | FD_CLOSE*/)
{
	if (WSAEventSelect(m_hSocket, m_hEvent, lEvent) == SOCKET_ERROR)
		return FALSE;
			
	m_lEvents = lEvent;
	return TRUE;
}

DWORD WINAPI CSunnyAsyncSocket::StaticThreadFunc(void* p)
{
	return ((CSunnyAsyncSocket*)p)->SocketFunc();
}
	
int	CSunnyAsyncSocket::SocketFunc()
{
	WSAEVENT hEvents[] = 
	{
		m_hStopEvent,
		m_ovRead.hEvent,
		m_ovWrite.hEvent,
		m_hEvent
	};
	WSANETWORKEVENTS netEvents;
	DWORD dwWaitRes;

	OnAttach();

	for(;;)
	{
		dwWaitRes = WSAWaitForMultipleEvents(
			sizeof(hEvents) / sizeof(WSAEVENT),
			hEvents,
			FALSE,
			m_dwTimeout,
			TRUE);
			
		if (dwWaitRes == WSA_WAIT_EVENT_0 + 3)
		{
			if (WSAEnumNetworkEvents(m_hSocket,	m_hEvent, &netEvents) != SOCKET_ERROR)
			{
				if ((netEvents.lNetworkEvents & FD_READ) == FD_READ)
					OnRead(netEvents.iErrorCode[FD_READ_BIT]);
					
				if ((netEvents.lNetworkEvents & FD_WRITE) == FD_WRITE)
					OnWrite(netEvents.iErrorCode[FD_WRITE_BIT]);

				if ((netEvents.lNetworkEvents & FD_CLOSE) == FD_CLOSE)
					OnClose(netEvents.iErrorCode[FD_CLOSE_BIT]);

				if ((netEvents.lNetworkEvents & FD_CONNECT) == FD_CONNECT)
					OnConnect(netEvents.iErrorCode[FD_CONNECT_BIT]);

				if((netEvents.lNetworkEvents & FD_ACCEPT) == FD_ACCEPT)
					OnAccept(netEvents.iErrorCode[FD_ACCEPT_BIT]);
			}
			else
			{
				int err = WSAGetLastError();
				if (err == WSANOTINITIALISED || err == WSAENOTSOCK)
					Close();
			}
		}
		else if (dwWaitRes == WSA_WAIT_EVENT_0)
			break;
		else if (dwWaitRes == WSA_WAIT_EVENT_0 + 1)
			_OnReadComplete();
		else if (dwWaitRes == WSA_WAIT_EVENT_0 + 2)
			_OnWriteComplete();
		else if (dwWaitRes == WSA_WAIT_FAILED)
			break;
		else if (dwWaitRes == WSA_WAIT_TIMEOUT)
			OnTimeout();
		else
			Close();
	}

	OnClear();

	if (m_fAutoDelete)
		delete this;

	return 0;
}

int CSunnyAsyncSocket::GetLastError() const
{
	return WSAGetLastError();
}

BOOL CSunnyAsyncSocket::Shutdown(int how /*= SD_BOTH*/)
{
	return (::shutdown(m_hSocket, how) != SOCKET_ERROR);
}

BOOL CSunnyAsyncSocket::Listen(int backlog /*= SOMAXCONN*/)
{
	return (::listen(m_hSocket, backlog) != SOCKET_ERROR);
}

BOOL CSunnyAsyncSocket::Attach(SOCKET hSocket)
{
	if (hSocket != INVALID_SOCKET)
	{
		Close();
		m_hSocket = hSocket;

		if (Select())
		{
			if (Bind(m_ipAddr))
			{
				if(Init())
					return TRUE;
			}
		}
	}

	return FALSE;
}

ACCEPTED_SOCKET CSunnyAsyncSocket::Accept() const
{
	ACCEPTED_SOCKET as;
	int nLen = sizeof(CIpAddress);

	as.hSocket = ::WSAAccept(m_hSocket, &as.ipAddr,	&nLen, NULL, 0);
	return as;
}

void CSunnyAsyncSocket::_OnReadComplete()
{
	DWORD dwLen;
	int nErrCode = 0;

	if (!GetOverlappedResult((HANDLE)m_hSocket, &m_ovRead, &dwLen, FALSE))
	{
		nErrCode = GetLastError();
		dwLen = 0;
	}

	ResetEvent(m_ovRead.hEvent);
	OnReadComplete(nErrCode, dwLen);
}

void CSunnyAsyncSocket::_OnWriteComplete()
{
	DWORD dwLen;
	int nErrCode = 0;

	if (!GetOverlappedResult((HANDLE)m_hSocket, &m_ovWrite, &dwLen, FALSE))
	{
		nErrCode = GetLastError();
		dwLen = 0;
	}
		
	ResetEvent(m_ovWrite.hEvent);
	OnWriteComplete(nErrCode, dwLen);
}

BOOL CSunnyAsyncSocket::Read(BYTE* p, DWORD dwLen)
{
	DWORD dwReaded;

	if (!ReadFile((HANDLE)m_hSocket, p, dwLen, &dwReaded, &m_ovRead))
	{
		DWORD dwErr = GetLastError();
		return (dwErr == ERROR_IO_PENDING);
	}

	return TRUE;
}

BOOL CSunnyAsyncSocket::Write(BYTE* p, DWORD dwLen)
{
	DWORD dwWriteded;

	if (!WriteFile((HANDLE)m_hSocket, p, dwLen, &dwWriteded, &m_ovWrite))
	{
		DWORD dwErr = GetLastError();
		return (dwErr == ERROR_IO_PENDING);
	}

	return TRUE;
}

void CSunnyAsyncSocket::SetThreadPriority(int nPriority /*= THREAD_PRIORITY_NORMAL*/)
{
	m_thread.SetPriority(nPriority);
}

void CSunnyAsyncSocket::OnClear()
{
	if (m_hSocket != INVALID_SOCKET)
	{
		Select(0);
		
		WSANETWORKEVENTS netEvents;
		if (WSAEnumNetworkEvents(m_hSocket, m_hEvent, &netEvents) != SOCKET_ERROR)
			Select(0);

		Select(0);
		Shutdown();
		::closesocket(m_hSocket);
		m_hSocket = INVALID_SOCKET;
	}
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -