📄 sunnyasyncsocket.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 + -