codepad
[
create a new paste
]
login
|
about
Language:
C
C++
D
Haskell
Lua
OCaml
PHP
Perl
Plain Text
Python
Ruby
Scheme
Tcl
//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) { [...] }
Private
[
?
]
Run code
Submit