Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. IOCP And WSANOBUFS Error

IOCP And WSANOBUFS Error

Scheduled Pinned Locked Moved C / C++ / MFC
comsysadminhelpquestion
8 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • P Offline
    P Offline
    Polity4h
    wrote on last edited by
    #1

    Hi, I'm writing a server application using UDP and the I/O Completion port. I red some articles and i know the things about it. My application scans a list of servers, requests some information, unpacks the information and stores the information, this is a process in loop. However, after a while i get the 10055 Error or better said WSANOBUFS. Now i red that that means that there cant be made any more locks ( source[^] ) I cant quit seem to find where the error takes place, there might be a sort of loop in locking where the the unlock never hits, but i dont know where that would be then. Is there any way to detect a possible deadlock? or do you know something else that might be wrong? Thanks already -Koen

    M 1 Reply Last reply
    0
    • P Polity4h

      Hi, I'm writing a server application using UDP and the I/O Completion port. I red some articles and i know the things about it. My application scans a list of servers, requests some information, unpacks the information and stores the information, this is a process in loop. However, after a while i get the 10055 Error or better said WSANOBUFS. Now i red that that means that there cant be made any more locks ( source[^] ) I cant quit seem to find where the error takes place, there might be a sort of loop in locking where the the unlock never hits, but i dont know where that would be then. Is there any way to detect a possible deadlock? or do you know something else that might be wrong? Thanks already -Koen

      M Offline
      M Offline
      Mark Salsbery
      wrote on last edited by
      #2

      Where are you getting the WSAENOBUFS error? On a send, receive, connect? If on a send, have you disabled send buffering for the socket? Are you using IOCP for sends, recvs, connects? All overlapped operations?

      P 1 Reply Last reply
      0
      • M Mark Salsbery

        Where are you getting the WSAENOBUFS error? On a send, receive, connect? If on a send, have you disabled send buffering for the socket? Are you using IOCP for sends, recvs, connects? All overlapped operations?

        P Offline
        P Offline
        Polity4h
        wrote on last edited by
        #3

        int res = WSARecvFrom(m_sSocket, &m_wsaBuf, 1, reinterpret_cast(&buflen), &temp, reinterpret_cast(&m_objAddress), &sockaddr_len, &m_objOverlapped, NULL); There i get the error 10055, Sending goes just fine. Since im using UDP im not connecting. Next to that, i dont use overlapped operations everywhere, i got a mysql class wich just sends a status update every 10 seconds, and a remote manager class wich uses TCP. both the mysql and the rmanager are using normal winsock so without overlapped operations. m_sSocket = socket(AF_INET, SOCK_DGRAM, 0); m_objAddress.sin_family = AF_INET; m_objLocalAddress.sin_family = AF_INET; m_objLocalAddress.sin_addr.s_addr = htonl(INADDR_ANY); m_objLocalAddress.sin_port = 0; m_hIOCP = hIOCP; if (bind(m_sSocket, reinterpret_cast(&m_objLocalAddress), sizeof(m_objLocalAddress))==SOCKET_ERROR){ TRACE("Error binding localaddress with the socket, Error: %i\n", WSAGetLastError()); } if (CreateIoCompletionPort(reinterpret_cast(m_sSocket), hIOCP, reinterpret_cast(const_cast(this)), 0)==NULL){ //Error binding? TRACE("Error binding Session to the main object, Error: %i\n", WSAGetLastError()); return; } Here i initialize is UDP session, there are like 400 udp virtual sessions continiously sending and recieving data. the first minut it goes all well, but after that, every sessions returns the error 10055 on recieving

        M 1 Reply Last reply
        0
        • P Polity4h

          int res = WSARecvFrom(m_sSocket, &m_wsaBuf, 1, reinterpret_cast(&buflen), &temp, reinterpret_cast(&m_objAddress), &sockaddr_len, &m_objOverlapped, NULL); There i get the error 10055, Sending goes just fine. Since im using UDP im not connecting. Next to that, i dont use overlapped operations everywhere, i got a mysql class wich just sends a status update every 10 seconds, and a remote manager class wich uses TCP. both the mysql and the rmanager are using normal winsock so without overlapped operations. m_sSocket = socket(AF_INET, SOCK_DGRAM, 0); m_objAddress.sin_family = AF_INET; m_objLocalAddress.sin_family = AF_INET; m_objLocalAddress.sin_addr.s_addr = htonl(INADDR_ANY); m_objLocalAddress.sin_port = 0; m_hIOCP = hIOCP; if (bind(m_sSocket, reinterpret_cast(&m_objLocalAddress), sizeof(m_objLocalAddress))==SOCKET_ERROR){ TRACE("Error binding localaddress with the socket, Error: %i\n", WSAGetLastError()); } if (CreateIoCompletionPort(reinterpret_cast(m_sSocket), hIOCP, reinterpret_cast(const_cast(this)), 0)==NULL){ //Error binding? TRACE("Error binding Session to the main object, Error: %i\n", WSAGetLastError()); return; } Here i initialize is UDP session, there are like 400 udp virtual sessions continiously sending and recieving data. the first minut it goes all well, but after that, every sessions returns the error 10055 on recieving

          M Offline
          M Offline
          Mark Salsbery
          wrote on last edited by
          #4

          This may or may not be the problem, but based on what I've seen it's the first thing that comes to mind. I hope this helps a bit... Unless you always keep enough receive buffers queued in your IOCP then the socket can receive datagrams faster than you are pulling them out of its buffer. If the socket is not "connected" (for UDP that just means all datagrams will be ignored except from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it sees on the network. You need to pull them out fast enough to keep enough buffer space for receives. One option is to use a connected socket to receive UDP datagrams on. The drawback is you'd need 400 sockets, or one for every session as you described. Another option is to always have a pool of overlapped WSARecvFrom() calls pushed on the IOCP stack so there will always be one available when a datagram is received. You could use the FD_READ notification to help notify a thread that data has been received on the socket and make sure there's a pending overlapped receive operation ready to accept the data. Also make sure your IOCP is properly "tuned" with the right amount of threads in the pool to most efficiently handle all the received datagrams. These articles may be helpful too (you may have seen them already - I keep them bookmarked for any IOCP troubles I encounter :))... Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports[^] INFO: Design Issues When Using IOCP in a Winsock Server[^]

          P 2 Replies Last reply
          0
          • M Mark Salsbery

            This may or may not be the problem, but based on what I've seen it's the first thing that comes to mind. I hope this helps a bit... Unless you always keep enough receive buffers queued in your IOCP then the socket can receive datagrams faster than you are pulling them out of its buffer. If the socket is not "connected" (for UDP that just means all datagrams will be ignored except from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it sees on the network. You need to pull them out fast enough to keep enough buffer space for receives. One option is to use a connected socket to receive UDP datagrams on. The drawback is you'd need 400 sockets, or one for every session as you described. Another option is to always have a pool of overlapped WSARecvFrom() calls pushed on the IOCP stack so there will always be one available when a datagram is received. You could use the FD_READ notification to help notify a thread that data has been received on the socket and make sure there's a pending overlapped receive operation ready to accept the data. Also make sure your IOCP is properly "tuned" with the right amount of threads in the pool to most efficiently handle all the received datagrams. These articles may be helpful too (you may have seen them already - I keep them bookmarked for any IOCP troubles I encounter :))... Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports[^] INFO: Design Issues When Using IOCP in a Winsock Server[^]

            P Offline
            P Offline
            Polity4h
            wrote on last edited by
            #5

            thanks, i havent solved the problem yet however i didnt try your possible solutions so :) I'll working on it as soon as my job ends. i'll tell you how it goes as soon as there's some result. thanks again

            1 Reply Last reply
            0
            • M Mark Salsbery

              This may or may not be the problem, but based on what I've seen it's the first thing that comes to mind. I hope this helps a bit... Unless you always keep enough receive buffers queued in your IOCP then the socket can receive datagrams faster than you are pulling them out of its buffer. If the socket is not "connected" (for UDP that just means all datagrams will be ignored except from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it sees on the network. You need to pull them out fast enough to keep enough buffer space for receives. One option is to use a connected socket to receive UDP datagrams on. The drawback is you'd need 400 sockets, or one for every session as you described. Another option is to always have a pool of overlapped WSARecvFrom() calls pushed on the IOCP stack so there will always be one available when a datagram is received. You could use the FD_READ notification to help notify a thread that data has been received on the socket and make sure there's a pending overlapped receive operation ready to accept the data. Also make sure your IOCP is properly "tuned" with the right amount of threads in the pool to most efficiently handle all the received datagrams. These articles may be helpful too (you may have seen them already - I keep them bookmarked for any IOCP troubles I encounter :))... Windows Sockets 2.0: Write Scalable Winsock Apps Using Completion Ports[^] INFO: Design Issues When Using IOCP in a Winsock Server[^]

              P Offline
              P Offline
              Polity4h
              wrote on last edited by
              #6

              If the socket is not "connected" (for UDP that just means all datagrams will be ignored except from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it sees on the network. You need to pull them out fast enough to keep enough buffer space for receives. I tried some solutions but i cant seem to get them working. Its probably my lack of experiance but well, The fundamental code: while (1){ BOOL bIORet = GetQueuedCompletionStatus ( // Get a completed IO request pThis->m_hIOCompiltionPort, &dwIoSize, reinterpret_cast(pThis), &ptrOverlapped, INFINITE); if (!bIORet){ TRACE("Winsock error code: %i\n", GetLastError()); Gameye::Library::Thread::CMPThread::Sleep(0); } else{ ptrSession = static_cast(ptrOverlapped->Pointer); CAbstractServerClass* ptrGameClass = (*pThis->m_ptrGameManager)[ptrSession->getNDServer()->GameID]; if (ptrGameClass == NULL){ TRACE("Game is unknown, probably removed\n"); } else{ objToolset.Session = ptrSession; switch(ptrSession->getTask()){ case RequestSend: //Request to send a packet if (WSASendTo(sSocket, ptrSession->getWSABuffer(), 1, reinterpret_cast(&ptrSession->getWSABuffer()->len), 0,reinterpret_cast(ptrSession->getAddress()), sizeof(sockaddr_in), ptrSession->getOverlapped(), NULL) == -1) { int iErrorCode = WSAGetLastError(); if (iErrorCode != 997){ //997 = Data is already recieved TRACE("Sending failed because: %i\n", WSAGetLastError()); break; } } ptrSession->setStatus(AfterSend); break; case RequestRecieve: //Request to recieve a packet if (WSARecvFrom(sSocket, ptrSession->getWSABuffer(), 1, reinterpret_cast(&ptrSession->getWSABuffer()->len), &iTemp,reinterpret_cast(ptrSession->getAddress()), &iSockAddrSize, ptrSession->getOverlapped(), NULL) == -1) { int iErrorCode = WSAGetLastError(); if (iErrorCode != 997){ //997 = Data is already recieved TRACE("Recieving failed because: %i\n", WSAGetLastError()); ptrSession->setStatus(AfterRecieve); } } ptrSession->setStatus(AfterRecieve);

              M 1 Reply Last reply
              0
              • P Polity4h

                If the socket is not "connected" (for UDP that just means all datagrams will be ignored except from the "connected" address) then the socket's recv buffer gets filled with every UDP datagram it sees on the network. You need to pull them out fast enough to keep enough buffer space for receives. I tried some solutions but i cant seem to get them working. Its probably my lack of experiance but well, The fundamental code: while (1){ BOOL bIORet = GetQueuedCompletionStatus ( // Get a completed IO request pThis->m_hIOCompiltionPort, &dwIoSize, reinterpret_cast(pThis), &ptrOverlapped, INFINITE); if (!bIORet){ TRACE("Winsock error code: %i\n", GetLastError()); Gameye::Library::Thread::CMPThread::Sleep(0); } else{ ptrSession = static_cast(ptrOverlapped->Pointer); CAbstractServerClass* ptrGameClass = (*pThis->m_ptrGameManager)[ptrSession->getNDServer()->GameID]; if (ptrGameClass == NULL){ TRACE("Game is unknown, probably removed\n"); } else{ objToolset.Session = ptrSession; switch(ptrSession->getTask()){ case RequestSend: //Request to send a packet if (WSASendTo(sSocket, ptrSession->getWSABuffer(), 1, reinterpret_cast(&ptrSession->getWSABuffer()->len), 0,reinterpret_cast(ptrSession->getAddress()), sizeof(sockaddr_in), ptrSession->getOverlapped(), NULL) == -1) { int iErrorCode = WSAGetLastError(); if (iErrorCode != 997){ //997 = Data is already recieved TRACE("Sending failed because: %i\n", WSAGetLastError()); break; } } ptrSession->setStatus(AfterSend); break; case RequestRecieve: //Request to recieve a packet if (WSARecvFrom(sSocket, ptrSession->getWSABuffer(), 1, reinterpret_cast(&ptrSession->getWSABuffer()->len), &iTemp,reinterpret_cast(ptrSession->getAddress()), &iSockAddrSize, ptrSession->getOverlapped(), NULL) == -1) { int iErrorCode = WSAGetLastError(); if (iErrorCode != 997){ //997 = Data is already recieved TRACE("Recieving failed because: %i\n", WSAGetLastError()); ptrSession->setStatus(AfterRecieve); } } ptrSession->setStatus(AfterRecieve);

                M Offline
                M Offline
                Mark Salsbery
                wrote on last edited by
                #7

                You get a completion packet indicating "RequestRecieve" and in response you call WSARecvFrom() before calling ptrSession->setStatus(AfterRecieve); Chances are pretty good that another thread has already processed the completion of the WSARecvFrom() call before you can even check the error code! :) So, you'll get ANOTHER RequestRecieve before you have a chance to set the session status to AfterRecieve. Make sense? In other words, you probably want to call ptrSession->setStatus(AfterRecieve) BEFORE you call WSARecvFrom(). Also, use WSA_IO_PENDING instead of 997 so I can read your code haha :) I don't have all the WSAE codes memorized yet ;P

                P 1 Reply Last reply
                0
                • M Mark Salsbery

                  You get a completion packet indicating "RequestRecieve" and in response you call WSARecvFrom() before calling ptrSession->setStatus(AfterRecieve); Chances are pretty good that another thread has already processed the completion of the WSARecvFrom() call before you can even check the error code! :) So, you'll get ANOTHER RequestRecieve before you have a chance to set the session status to AfterRecieve. Make sense? In other words, you probably want to call ptrSession->setStatus(AfterRecieve) BEFORE you call WSARecvFrom(). Also, use WSA_IO_PENDING instead of 997 so I can read your code haha :) I don't have all the WSAE codes memorized yet ;P

                  P Offline
                  P Offline
                  Polity4h
                  wrote on last edited by
                  #8

                  Nope, that aint the proble. would be really quick ;) and srry about the code, its just a test project. when i got it all working i'm gonna merch it and mostly rewrite it. Thanks anyway

                  1 Reply Last reply
                  0
                  Reply
                  • Reply as topic
                  Log in to reply
                  • Oldest to Newest
                  • Newest to Oldest
                  • Most Votes


                  • Login

                  • Don't have an account? Register

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • World
                  • Users
                  • Groups