Note that there are some explanatory texts on larger screens.

plurals
  1. POWinsock: Overlapped AcceptEx indicates a new connection while no client connecting
    primarykey
    data
    text
    <p>In my program I am using the overlapped version of <code>AcceptEx()</code> to accept new connections. After a new connection has been accepted, the programm initiates another overlapped call to <code>AcceptEx()</code> for accepting more connections. This works fine and I can connect multiple clients to the server successfully.</p> <p>But if I just connect one client and let the server-application call WSARecv (overlapped) on this socket, <code>AcceptEx()</code> magically accepts a new "ghost"-connection (There is the first client running doing nothing). When I call <code>WSARecv</code> on that, of course - it gives an error.</p> <p>The program incorporates an <strong>I/O-Completion Port</strong> for all the overlapped calls.</p> <p>I don´t know where the fake connection comes from. But that it seems to be a bug in my code that I am unable to find.</p> <p>Things i can definetly exclude from being the errors reason: 1.The <strong>overlapped-structures</strong> i use and the parameter for casting works correct. 2. The <strong>IOCP-wrapper class</strong>.</p> <p>Following is the relevant code (in my opinion) - if You need more, tell me, please :)</p> <pre><code>//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-&gt;AssociateHandle((HANDLE) m_pListenSocket-&gt;operator size_t(), 2)) return Inc::INC_FATAL; [...] } CServer::InitAcceptorSocket(const std::wstring&amp; strLocalAddress, const std::wstring&amp; 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-&gt;Bind(Inc::WStringToString(strLocalAddress), Inc::WStringToString(strListenPort))) //Works as bind just calls getadrrinfo within itself //Put the socket into listen mode if(!m_pListenSocket-&gt;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-&gt;DoWork(); }; } catch(Inc::CException&amp; e) { DebugBreak(); } return 0; } bool CServer::DoWork() { DWORD dwBytes = 0; ULONG_PTR ulKey = 0; OVERLAPPED* pOverlapped = nullptr; //Dequeue a completion packet if(!m_pIOCP-&gt;GetCompletionStatus(&amp;dwBytes, &amp;ulKey, &amp;pOverlapped, INFINITE)) { //error stuff } //Check for termination request: if(!dwBytes &amp;&amp; !ulKey &amp;&amp; !pOverlapped) return false; //Convert the Overlapped and check which work has to be done switch(((MYOVERLAPPED*)pOverlapped)-&gt;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&lt;Inc::CSocket&gt; pSocket(new Inc::CSocket(pWork-&gt;SocketNewConnection)); //obtains the nescessary information (like AF_INET , etc by calls to getsockopt - works fine) //Associate with the IOCP if(!m_pIOCP-&gt;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-&gt;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&lt;WORK_RECV&gt; pWorkRecv(new WORK_RECV); memset((OVERLAPPED*)pWorkRecv.get(), 0, sizeof(OVERLAPPED)); pWorkRecv-&gt;pSocket = pSocket; //Call Recv std::string strRecvBuffer; //temporary receive buffer for immediate completion short sRet = pSocket-&gt;Recv(strRecvBuffer, pWorkRecv-&gt;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&lt;WORK_ACCEPT&gt; pWork(new WORK_ACCEPT); memset((OVERLAPPED*)pWork.get(), 0, sizeof(OVERLAPPED)); pWork-&gt;pListenSocket = pListenSocket; pWork-&gt;pSocket = m_pListenSocket.get(); //Call accept pWork-&gt;SocketNewConnection = m_pListenSocket-&gt;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 &amp; 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), &amp;dwBytes, pOverlapped) == FALSE) { int nError = WSAGetLastError(); if(nError != WSA_IO_PENDING) throw(Inc::CException(nError, "AcceptEx failed.")); return ClientSock; } //if immidiately &amp; successfully connected, get the client address [...] return ClientSock; } } //The receive function short Inc::CSocket::RecvHelper(std::string&amp; strIncomingDataBuffer, WSABUF*&amp; 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&lt;char[]&gt; pcBuf(new char[nBytesToRecv]); //create the WSABUF std::unique_ptr&lt;WSABUF&gt; pWSABufBuf (new WSABUF); pWSABufBuf-&gt;len = nBytesToRecv; pWSABufBuf-&gt;buf = pcBuf.get(); iRet = WSARecv(m_Socket, pWSABufBuf.get(), 1, pOverlapped ? NULL : (&amp;dwReceived), &amp;dwFlags, pOverlapped, NULL); if(iRet == 0) { //closed (gracefully) by the client (indicated by zero bytes returned) if(dwReceived == 0 &amp;&amp; (!pOverlapped)) return REMOTECONNECTION_CLOSED; //return //successfull received strIncomingDataBuffer.assign(pWSABufBuf-&gt;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) { [...] } </code></pre> <p><strong>EDIT: Wrote a test-server which works just fine</strong></p> <pre><code>//Accept a new connection ACCEPTLAPPED* pOverAccept = new ACCEPTLAPPED; pOverAccept-&gt;pSockListen = &amp;SockListen; pOverAccept-&gt;pSockClient = new Inc::CSocket(SockListen.Accept(nullptr, nullptr, pOverAccept)); //Main loop DWORD dwBytes = 0, dwFlags = 0; ULONG_PTR ulKey = 0; OVERLAPPED* pOverlapped = nullptr; while(true) { dwBytes = 0; dwFlags = 0; ulKey = 0; pOverlapped = nullptr; //Dequeue a packet pIOCP-&gt;GetCompletionStatus(&amp;dwBytes, &amp;ulKey, &amp;pOverlapped, INFINITE); switch(((BASELAPPED*)pOverlapped)-&gt;Type) { case 1: //Accept { //ASsociate handle ACCEPTLAPPED* pOld = (ACCEPTLAPPED*)pOverlapped; pIOCP-&gt;AssociateHandle((HANDLE)(pOld-&gt;pSockClient)-&gt;operator SOCKET(),2); //call recv RECVLAPPED* pRecvLapped = new RECVLAPPED; pRecvLapped-&gt;pSockClient = pOld-&gt;pSockClient; short sRet = (pRecvLapped-&gt;pSockClient)-&gt;Recv(pRecvLapped-&gt;strBuf, pRecvLapped-&gt;pBuf, 10, pRecvLapped); //Call accept again ACCEPTLAPPED* pNewAccLapp = new ACCEPTLAPPED; pNewAccLapp-&gt;pSockListen = ((ACCEPTLAPPED*)pOverlapped)-&gt;pSockListen; pNewAccLapp-&gt;pSockClient = new Inc::CSocket((pNewAccLapp-&gt;pSockListen)-&gt;Accept(nullptr, nullptr, pNewAccLapp)); delete pOverlapped; }; break; case 2: //Recv { RECVLAPPED* pOld = (RECVLAPPED*)pOverlapped; if(!pOverlapped-&gt;InternalHigh) { delete pOld-&gt;pSockClient; Inc::CSocket::freewsabufpointer(&amp;(pOld-&gt;pBuf)); delete pOld; break; }; cout &lt;&lt; std::string(pOld-&gt;pBuf-&gt;buf, pOld-&gt;pBuf-&gt;len) &lt;&lt;endl; </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload