[ create a new paste ] login | about

Link: http://codepad.org/nrTmfUjR    [ raw code | fork ]

C++, pasted on Sep 6:
//schematic
main()
{
	Server.Init(...);
	Server.Start();			//Run-loop
}

CServer::Init(/*...*/)
{
	[...]


	//Create the listen socket...
	Ret = InitAcceptorSocket(strLocalAddress, strListenPort, nBacklog);
	if(Ret != Inc::INC_OK)
		return Ret;

	//...Associate it with the IOCP
	if(!m_pIOCP->AssociateHandle((HANDLE) m_pListenSocket->operator size_t(), 2))
		return Inc::INC_FATAL;

	[...]
}

CServer::InitAcceptorSocket(const std::wstring& strLocalAddress, const std::wstring& strListenPort, int nBacklog)
{
	//Create the socket
	m_pListenSocket.reset(new Inc::CSocket(AF_INET, SOCK_STREAM, IPPROTO_TCP));

	//Bind to specific port
	if(!m_pListenSocket->Bind(Inc::WStringToString(strLocalAddress), Inc::WStringToString(strListenPort)))		//Works as bind just calls getadrrinfo within itself

	//Put the socket into listen mode
	if(!m_pListenSocket->Listen(nBacklog))		//simple listen-wrapper: just calls the function and returns status indication
}

//Starts the server's work-cycle
CServer::Start(/**/)
{
	//Call accept
	DoCallAccept(m_pListenSocket.get());

	//Resume the threads
	//std::for_each(m_vecThreadHandles.begin(), m_vecThreadHandles.end(), [] (HANDLE hThread) {::ResumeThread(hThread);} );

	//TEST: Enter the Loop, too
	ServerMainWorkerThreadProc(this);

	return Inc::INC_OK;
}


//Worker thread proc
uintptr_t WINAPI ServerMainWorkerThreadProc(void* pvArgs)
{
	CServer* pServer = (CServer*)pvArgs;
	bool bLooping = true;

	try
	{
		while(bLooping)
		{
			bLooping = pServer->DoWork();
		};
	}
	catch(Inc::CException& e)
	{
		DebugBreak();
	}

	return 0;
}


bool CServer::DoWork()
{

	DWORD dwBytes = 0;
	ULONG_PTR ulKey = 0;
	OVERLAPPED* pOverlapped = nullptr;

	//Dequeue a completion packet
	if(!m_pIOCP->GetCompletionStatus(&dwBytes, &ulKey, &pOverlapped, INFINITE))
	{
		//error stuff
	}

	//Check for termination request:
	if(!dwBytes && !ulKey && !pOverlapped)
		return false;

	//Convert the Overlapped and check which work has to be done
	switch(((MYOVERLAPPED*)pOverlapped)->WorkType)
	{
	case WT_ACCEPT:					//A new connection has been accepted
		HandleAcceptedConnection((WORK_ACCEPT*)pOverlapped);
		break;
	case WT_SEND:					//Send data
		//HandleSendRequest((WORK_SEND*)pOverlapped);
		break;
	case WT_RECV:					//Data has been received
		//HandleReceivedData((WORK_RECV*)pOverlapped);
		break;
	[...]
		
	return true;
}

	//New connection has been accepted
bool CServer::HandleAcceptedConnection(WORK_ACCEPT* pWork)
{
	//Create a new client socket object
	std::unique_ptr<Inc::CSocket> pSocket(new Inc::CSocket(pWork->SocketNewConnection));		//obtains the nescessary information (like AF_INET , etc by calls to getsockopt - works fine)

	//Associate with the IOCP
	if(!m_pIOCP->AssociateHandle((HANDLE)((SOCKET)(*(pSocket.get()))), 2))
	{
		//Report the error
	}

	//Queue a recv-packet
	if(!DoCallRecv(pSocket.get()))
	{
		//Report the error
	}

	//Release the client-socket-object
	pSocket.release();

	//Call accept another time
	DoCallAccept(pWork->pListenSocket);

	//Cleanuo
	delete pWork;

	return true;
}


//Call Recv on the socket
bool CServer::DoCallRecv(Inc::CSocket* pSocket)
{
	//Create the work object for receiving data
	std::unique_ptr<WORK_RECV> pWorkRecv(new WORK_RECV);
	memset((OVERLAPPED*)pWorkRecv.get(), 0, sizeof(OVERLAPPED));
	pWorkRecv->pSocket = pSocket;


	//Call Recv
	std::string strRecvBuffer;		//temporary receive buffer for immediate completion
	short sRet = pSocket->Recv(strRecvBuffer, pWorkRecv->pTestWSABuf, 2048, (OVERLAPPED*)pWorkRecv.get());
	[...]
	if(sRet == Inc::REMOTETRANSACTION_PENDING)
	{
		//release the work item so it is still on the heap when the overlapped operation completes
		pWorkRecv.release();
	}

	return true;
}

//Queue a call to accept
bool CServer::DoCallAccept(Inc::CSocket* pListenSocket)
{
	//Create the overlapped-structure
	std::unique_ptr<WORK_ACCEPT> pWork(new WORK_ACCEPT);
	memset((OVERLAPPED*)pWork.get(), 0, sizeof(OVERLAPPED));
	pWork->pListenSocket = pListenSocket;
	pWork->pSocket = m_pListenSocket.get();

	//Call accept
	pWork->SocketNewConnection = m_pListenSocket->Accept(nullptr, nullptr, (OVERLAPPED*)pWork.get());

	//Release the work object
	pWork.release();

	return true;
}


//The accept function for My custom socket-wrapper-class
SOCKET Inc::CSocket::Accept(sockaddr_storage* pAddr, int* pAddrLen, OVERLAPPED* pOverlapped)
{
	[...]
	else		//Overlapped
	{
		//create the client socket
		SOCKET ClientSock = socket(m_SocketAF, SOCK_STREAM, 0);
		if(ClientSock == INVALID_SOCKET)
			throw(Inc::CException(WSAGetLastError(), "Socket creation failed."));
		//address structure & size
		sockaddr_storage *ClientAddress = {0}; DWORD dwClientAddressSize = sizeof(sockaddr_storage);
		//output buffer
		//char acOutputBuffer[(2 * sizeof(sockaddr_storage)) + 32] = "";
		//received bytes
		DWORD dwBytes = 0;

		if(m_lpfnAcceptEx(m_Socket, ClientSock, (PVOID)m_acOutputBuffer, 0, (dwClientAddressSize + 16), (dwClientAddressSize + 16), &dwBytes, pOverlapped) == FALSE)
		{
			int nError = WSAGetLastError();
			if(nError != WSA_IO_PENDING)
				throw(Inc::CException(nError, "AcceptEx failed."));

			return ClientSock;
		}

		//if immidiately & successfully connected, get the client address
		[...]

		return ClientSock;
	}
}


//The receive function
short Inc::CSocket::RecvHelper(std::string& strIncomingDataBuffer, WSABUF*& pWSABuf, unsigned int nBytesToRecv, OVERLAPPED* pOverlapped)
{
	int iRet = 0;					//ret code
	DWORD dwReceived = 0, dwFlags = 0;

	//Clear the Buffer
	strIncomingDataBuffer.clear();

	//create the receiving buffer
	std::unique_ptr<char[]> pcBuf(new char[nBytesToRecv]);
	//create the WSABUF
	std::unique_ptr<WSABUF> pWSABufBuf (new WSABUF);
	pWSABufBuf->len = nBytesToRecv;
	pWSABufBuf->buf = pcBuf.get();


	iRet = WSARecv(m_Socket, pWSABufBuf.get(), 1, pOverlapped ? NULL : (&dwReceived), &dwFlags, pOverlapped, NULL);
	if(iRet == 0)
	{
		//closed (gracefully) by the client (indicated by zero bytes returned)
		if(dwReceived == 0 && (!pOverlapped))
			return REMOTECONNECTION_CLOSED;		//return

		//successfull received
		strIncomingDataBuffer.assign(pWSABufBuf->buf, dwReceived);

		return SUCCESS;
	}
	if(iRet == SOCKET_ERROR)
	{
		int nError = WSAGetLastError();

		//Overlapped transaction initiated successfully
		//waiting for completion
		if(nError == WSA_IO_PENDING)
		{
			//release the buffers
			pcBuf.release();
			pWSABuf = pWSABufBuf.release();		//hand it over to the user

			return REMOTETRANSACTION_PENDING;	//return "transaction pending"-status
		}

		//forced closure(program forced to exit)
		if(nError == WSAECONNRESET)
		{
		[...]
}


Create a new paste based on this one


Comments: